Lumaktaw sa pangunahing nilalaman

Mga yugto ng Transpiler

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.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1

Inilalarawan ng pahinang ito ang mga yugto ng prebuilt transpilation pipeline sa Qiskit SDK. May anim na yugto:

  1. init
  2. layout
  3. routing
  4. translation
  5. optimization
  6. scheduling

Ang function na generate_preset_pass_manager ay gumagawa ng preset na staged pass manager na binubuo ng mga yugto na ito. Ang mga tiyak na pass na bumubuo sa bawat yugto ay nakasalalay sa mga argumento na ipinasa sa generate_preset_pass_manager. Ang optimization_level ay isang positional argument na dapat tukuyin; ito ay isang integer na maaaring 0, 1, 2, o 3. Ang mas mataas na halaga ay nagpapahiwatig ng mas mabigat ngunit mas mahal na optimization (tingnan ang Mga default na setting at opsyon sa configuration ng transpilation).

Ang inirerekomendang paraan para i-transpile ang isang Circuit ay ang lumikha ng preset staged pass manager at pagkatapos ay patakbuhin ang pass manager na iyon sa Circuit, gaya ng inilarawan sa Mag-transpile gamit ang mga pass manager. Gayunpaman, may mas simpleng ngunit hindi gaanong nako-customize na alternatibo β€” ang paggamit ng function na transpile. Tinatanggap ng function na ito ang Circuit nang direkta bilang argumento. Tulad ng sa generate_preset_pass_manager, ang mga tiyak na transpiler pass na ginagamit ay nakasalalay sa mga argumento, tulad ng optimization_level, na ipinasa sa transpile. Sa katunayan, sa loob ng transpile function, tinatawagan nito ang generate_preset_pass_manager para lumikha ng preset staged pass manager at pinapatakbo ito sa Circuit.

Init stage​

Ang unang yugto na ito ay halos walang ginagawa bilang default at pangunahing kapaki-pakinabang kung gusto mong isama ang iyong sariling mga paunang optimization. Dahil karamihan sa mga layout at routing algorithm ay idinisenyo lamang para magtrabaho sa single- at two-qubit gate, ginagamit din ang yugtong ito para isalin ang anumang gate na gumagana sa higit sa dalawang qubit sa mga gate na gumagana lamang sa isa o dalawang qubit.

Para sa karagdagang impormasyon tungkol sa pagpapatupad ng iyong sariling mga paunang optimization para sa yugtong ito, tingnan ang seksyon sa mga plugin at pag-customize ng mga pass manager.

Layout stage​

Ang susunod na yugto ay kinabibilangan ng layout o connectivity ng Backend na padadalhang Circuit. Sa pangkalahatan, ang mga quantum circuit ay mga abstract na entity na ang mga qubit ay "virtual" o "logical" na representasyon ng mga tunay na qubit na ginagamit sa mga computation. Para maisagawa ang isang pagkakasunud-sunod ng mga Gate, kinakailangan ang isang one-to-one na mapping mula sa "virtual" na mga qubit patungo sa "physical" na mga qubit sa isang tunay na quantum device. Ang mapping na ito ay naka-imbak bilang isang Layout na object at bahagi ng mga constraint na tinukoy sa loob ng instruction set architecture (ISA) ng isang Backend.

Inilalarawan ng larawang ito ang mga qubit na nima-map mula sa wire representation patungo sa isang diagram na kumakatawan sa kung paano konektado ang mga qubit sa QPU.

Napakahalaga ng pagpili ng mapping para mabawasan ang bilang ng mga SWAP operation na kailangan para ma-map ang input Circuit sa device topology at matiyak na ang mga pinaka-well-calibrated na qubit ang gagamitin. Dahil sa kahalagahan ng yugtong ito, sinusubukan ng mga preset pass manager ang ilang iba't ibang paraan para mahanap ang pinakamainam na layout. Karaniwang nagsasangkot ito ng dalawang hakbang: una, subukang mahanap ang isang "perpekto" na layout (isang layout na hindi nangangailangan ng anumang SWAP operation), at pagkatapos, isang heuristic pass na nagsisikap na mahanap ang pinakamainam na layout na gagamitin kung hindi mahanap ang perpektong layout. May dalawang Passes na karaniwang ginagamit para sa unang hakbang na ito:

  • TrivialLayout: Simpleng nagma-map ng bawat virtual qubit sa parehong numbered na physical qubit sa device (hal., [0,1,1,3] -> [0,1,1,3]). Ito ay makasaysayang gawi na ginagamit lamang sa optimzation_level=1 para subukang mahanap ang perpektong layout. Kung mabigo ito, susunod na susubukan ang VF2Layout.
  • VF2Layout: Ito ay isang AnalysisPass na pumipili ng ideal na layout sa pamamagitan ng pagtrato sa yugtong ito bilang isang subgraph isomorphism problem, na nalulutas ng VF2++ algorithm. Kung mahiit sa isang layout ang mahanap, nagpapatakbo ng scoring heuristic para piliin ang mapping na may pinakamababang average error.

Pagkatapos para sa heuristic stage, dalawang pass ang ginagamit bilang default:

  • DenseLayout: Hinahanap ang sub-graph ng device na may pinakamataas na connectivity at may parehong bilang ng mga qubit gaya ng Circuit (ginagamit para sa optimization level 1 kung may mga control flow operation (tulad ng IfElseOp) na naroroon sa Circuit).
  • SabreLayout: Pinipili ng pass na ito ang isang layout sa pamamagitan ng pagsisimula mula sa isang paunang random na layout at paulit-ulit na pagpapatakbo ng SabreSwap algorithm. Ginagamit lamang ang pass na ito sa mga optimization level 1, 2, at 3 kung hindi mahanap ang perpektong layout sa pamamagitan ng VF2Layout pass. Para sa karagdagang detalye tungkol sa algorithm na ito, tingnan ang papel na arXiv:1809.02573.

Routing stage​

Para mapatupad ang isang two-qubit gate sa pagitan ng mga qubit na hindi direktang konektado sa isang quantum device, kailangang maglagay ng isa o higit pang SWAP gate sa Circuit para maililipat ang mga qubit state hanggang sa maging magkatabing muli sila sa device gate map. Bawat SWAP gate ay kumakatawan sa isang mahal at maingay na operasyon na isasagawa. Kaya naman, ang paghahanap ng pinakamaliit na bilang ng mga SWAP gate na kailangan para ma-map ang isang Circuit sa isang ibinigay na device ay isang mahalagang hakbang sa proseso ng transpilation. Para sa kahusayan, ang yugtong ito ay karaniwang kinakalkula kasabay ng Layout stage bilang default, ngunit lohikal silang naiiba sa isa't isa. Ang Layout stage ay pumipili ng mga hardware qubit na gagamitin, habang ang Routing stage ay naglalagay ng angkop na dami ng SWAP gate para maisagawa ang mga Circuit gamit ang napiling layout.

Gayunpaman, mahirap mahanap ang optimal na SWAP mapping. Sa katunayan, ito ay isang NP-hard problem, at samakatuwid ay labis na mahal para kalkulahin para sa lahat maliban sa pinakamaliit na mga quantum device at input circuit. Para malampasan ito, gumagamit ang Qiskit ng stochastic heuristic algorithm na tinatawag na SabreSwap para makalkula ang isang maganda ngunit hindi necessarily optimal na SWAP mapping. Ang paggamit ng stochastic na pamamaraan ay nangangahulugang ang mga circuit na nabuo ay hindi garantisadong magiging pareho sa magkakasunod na pagpapatakbo. Sa katunayan, ang paulit-ulit na pagpapatakbo ng parehong Circuit ay nagbubunga ng distribusyon ng mga circuit depth at bilang ng gate sa output. Ito ang dahilan kung bakit maraming gumagamit ang pumipili na patakbuhin ang routing function (o ang buong StagedPassManager) nang maraming beses at piliin ang mga Circuit na may pinakamababang depth mula sa distribusyon ng mga output.

Halimbawa, tingnan natin ang isang 15-qubit GHZ circuit na pinatakbo nang 100 beses, gamit ang isang "masamang" (disconnected) na initial_layout.

# Added by doQumentation β€” required packages for this notebook
!pip install -q matplotlib qiskit qiskit-ibm-runtime
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeAuckland, FakeWashingtonV2
from qiskit.transpiler import generate_preset_pass_manager

backend = FakeAuckland()

ghz = QuantumCircuit(15)
ghz.h(0)
ghz.cx(0, range(1, 15))

depths = []
for seed in range(100):
pass_manager = generate_preset_pass_manager(
optimization_level=1,
backend=backend,
layout_method="trivial", # Fixed layout mapped in circuit order
seed_transpiler=seed, # For reproducible results
)
depths.append(pass_manager.run(ghz).depth())

plt.figure(figsize=(8, 6))
plt.hist(depths, align="left", color="#AC557C")
plt.xlabel("Depth", fontsize=14)
plt.ylabel("Counts", fontsize=14)
Text(0, 0.5, 'Counts')

Output of the previous code cell

Ipinapakita ng malawak na distribusyong ito kung gaano kahirap para sa SWAP mapper na kalkulahin ang pinakamainam na mapping. Para makakuha ng kaunting pananaw, tingnan natin ang Circuit na pinapatakbo pati na rin ang mga qubit na pinili sa hardware.

ghz.draw("mpl", idle_wires=False)

Output of the previous code cell

from qiskit.visualization import plot_circuit_layout

# Plot the hardware graph and indicate which hardware qubits were chosen to run the circuit
transpiled_circ = pass_manager.run(ghz)
plot_circuit_layout(transpiled_circ, backend)

Output of the previous code cell

Gaya ng makikita, kailangang magsagawa ang Circuit na ito ng isang two-qubit gate sa pagitan ng mga qubit 0 at 14, na napakalayo sa connectivity graph. Ang pagpapatakbo ng Circuit na ito ay nangangailangan ng paglalagay ng mga SWAP gate para maisagawa ang lahat ng two-qubit gate gamit ang SabreSwap pass.

Tandaan din na ang SabreSwap algorithm ay naiiba mula sa mas malaking SabreLayout na pamamaraan sa nakaraang yugto. Bilang default, pinapatakbo ng SabreLayout ang parehong layout at routing, at ibinalik ang na-transform na Circuit. Ginagawa ito para sa ilang partikular na teknikal na dahilan na tinukoy sa API reference page ng pass.

Translation stage​

Kapag nagsusulat ng quantum circuit, malaya kang gumamit ng anumang quantum gate (unitary operation) na gusto mo, kasama ang koleksyon ng mga non-gate na operasyon tulad ng mga tagubilin sa pagsukat ng qubit o reset. Gayunpaman, karamihang quantum device ay likas na sumusuporta lamang sa iilang quantum gate at non-gate na operasyon. Ang mga native gate na ito ay bahagi ng kahulugan ng ISA ng isang target at ang yugtong ito ng preset na PassManagers ay nagsasalin (o unrolls) ng mga gate na tinukoy sa isang Circuit sa mga native basis gate ng isang tinukoy na Backend. Ito ay isang mahalagang hakbang, dahil pinapayagan nito ang Circuit na maisagawa ng Backend, ngunit karaniwang nagdudulot ng pagtaas sa depth at bilang ng mga Gate.

Dalawang espesyal na kaso ang partikular na mahalaga na i-highlight, at nakakatulong silang ilarawan kung ano ang ginagawa ng yugtong ito.

  1. Kung ang isang SWAP gate ay hindi isang native gate sa target na Backend, nangangailangan ito ng tatlong CNOT gate:
print("native gates:" + str(sorted(backend.operation_names)))
qc = QuantumCircuit(2)
qc.swap(0, 1)
qc.decompose().draw("mpl")
native gates:['cx', 'delay', 'for_loop', 'id', 'if_else', 'measure', 'reset', 'rz', 'switch_case', 'sx', 'x']

Output of the previous code cell

Bilang produkto ng tatlong CNOT gate, ang isang SWAP ay isang mahal na operasyon na isasagawa sa mga maingay na quantum device. Gayunpaman, karaniwang kailangan ang ganitong mga operasyon para ma-embed ang isang Circuit sa limitadong gate connectivity ng maraming device. Kaya naman, ang pagbabawas ng bilang ng mga SWAP gate sa isang Circuit ay isang pangunahing layunin sa proseso ng transpilation.

  1. Ang Toffoli, o controlled-controlled-not gate (ccx), ay isang three-qubit gate. Dahil ang aming basis gate set ay kinabibilangan lamang ng single- at two-qubit gate, ang operasyong ito ay kailangang i-decompose. Gayunpaman, ito ay medyo mahal:
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
qc.decompose().draw("mpl")

Output of the previous code cell

Para sa bawat Toffoli gate sa isang quantum circuit, maaaring magsagawa ang hardware ng hanggang anim na CNOT gate at ilang single-qubit gate. Ipinapakita ng halimbawang ito na ang anumang algorithm na gumagamit ng maraming Toffoli gate ay magtatapos bilang isang Circuit na may malaking depth at samakatuwid ay makabuluhang maaapektuhan ng ingay.

Optimization stage​

Ang yugtong ito ay nakatuon sa pag-decompose ng mga quantum circuit sa basis gate set ng target na device, at kailangang labanan ang pagtaas ng depth mula sa mga layout at routing stage. Sa kabutihang palad, maraming gawain para sa pag-optimize ng mga Circuit sa pamamagitan ng pagsasama o pag-aalis ng mga Gate. Sa ilang kaso, napaka-epektibo ng mga pamamaraang ito kaya ang mga output circuit ay may mas mababang depth kaysa sa mga input, kahit na pagkatapos ng layout at routing sa hardware topology. Sa ibang kaso, hindi masyadong magagawa, at maaaring mahirap isagawa ang computation sa mga maingay na device. Ito ang yugto kung saan nagsisimulang mag-iba ang iba't ibang optimization level.

Bukod dito, nagsasagawa rin ang yugtong ito ng ilang panghuling pagsusuri para matiyak na ang lahat ng tagubilin sa Circuit ay binubuo ng mga basis gate na available sa target na Backend.

Ipinapakita ng halimbawa sa ibaba gamit ang isang GHZ state ang mga epekto ng iba't ibang setting ng optimization level sa circuit depth at bilang ng gate.

tala

Nag-iiba-iba ang output ng transpilation dahil sa stochastic SWAP mapper. Kaya naman, ang mga numerong nasa ibaba ay malamang na magbabago sa bawat beses na patakbuhin mo ang code.

15-qubit GHZ state

Ang sumusunod na code ay gumagawa ng isang 15-qubit GHZ state at inihambing ang mga optimization_levels ng transpilation sa mga tuntunin ng resultang circuit depth, bilang ng gate, at bilang ng multi-qubit gate.

ghz = QuantumCircuit(15)
ghz.h(0)
ghz.cx(0, range(1, 15))

depths = []
gate_counts = []
multiqubit_gate_counts = []
levels = [str(x) for x in range(4)]
for level in range(4):
pass_manager = generate_preset_pass_manager(
optimization_level=level,
backend=backend,
seed_transpiler=1234,
)
circ = pass_manager.run(ghz)
depths.append(circ.depth())
gate_counts.append(sum(circ.count_ops().values()))
multiqubit_gate_counts.append(circ.count_ops()["cx"])

fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.bar(levels, depths, label="Depth")
ax1.set_xlabel("Optimization Level")
ax1.set_ylabel("Depth")
ax1.set_title("Output Circuit Depth")
ax2.bar(levels, gate_counts, label="Number of Circuit Operations")
ax2.bar(levels, multiqubit_gate_counts, label="Number of CX gates")
ax2.set_xlabel("Optimization Level")
ax2.set_ylabel("Number of gates")
ax2.legend()
ax2.set_title("Number of output circuit gates")
fig.tight_layout()
plt.show()

Output of the previous code cell

Scheduling​

Ang huling yugtong ito ay pinapatakbo lamang kung ito ay tahasan na hinihingi (katulad ng Init stage) at hindi tumatakbo bilang default (bagaman maaaring tukuyin ang isang pamamaraan sa pamamagitan ng pagtatakda ng argumentong scheduling_method kapag tinatawagan ang generate_preset_pass_manager). Karaniwang ginagamit ang scheduling stage kapag na-translate na ang Circuit sa target basis, na-map sa device, at na-optimize. Ang mga pass na ito ay nakatuon sa pag-account para sa lahat ng idle time sa isang Circuit. Sa mataas na antas, ang scheduling pass ay maaaring isipin bilang tahasan na paglalagay ng mga delay na tagubilin para mag-account para sa idle time sa pagitan ng mga gate execution at para suriin kung gaano katagal ang Circuit na tumatakbo sa Backend.

Narito ang isang halimbawa:

ghz = QuantumCircuit(5)
ghz.h(0)
ghz.cx(0, range(1, 5))

# Use fake backend
backend = FakeWashingtonV2()

# Run with optimization level 3 and 'asap' scheduling pass
pass_manager = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
scheduling_method="asap",
seed_transpiler=1234,
)

circ = pass_manager.run(ghz)
circ.draw(output="mpl", idle_wires=False)

Output of the previous code cell

Circuit na may mga delay na tagubilin

Naglagay ang Transpiler ng mga tagubiling Delay para mag-account para sa idle time sa bawat qubit. Para mas maintindihan ang timing ng Circuit maaari rin nating tingnan ito gamit ang function na timeline.draw():

timeline.draw() na view ng parehong Circuit Ang pag-schedule ng isang Circuit ay nagsasangkot ng dalawang bahagi: analysis at constraint mapping, na sinusundan ng isang padding pass. Ang unang bahagi ay nangangailangan ng pagpapatakbo ng scheduling analysis pass (bilang default ito ay ALAPSchedulingAnalysis), na nag-aanalisa ng Circuit at nagtatala ng oras ng pagsisimula ng bawat tagubilin sa Circuit sa isang schedule. Kapag mayroon nang paunang schedule ang Circuit, maaaring patakbuhin ang mga karagdagang pass para mag-account para sa anumang timing constraint sa target na Backend. Sa wakas, maaaring isagawa ang isang padding pass tulad ng PadDelay o PadDynamicalDecoupling.

Mga susunod na hakbang​

Mga Rekomendasyon