Utility-scale experiment I
Tamiya Onodera (5 Hulyo 2024)
I-download ang pdf ng orihinal na lektura. Tandaan na maaaring maging deprecated ang ilang code snippet dahil static na mga imahe ang mga ito.
Ang tinatayang oras ng QPU para patakbuhin ang eksperimentong ito ay 45 segundo.
1. Panimula sa utility paper
Sa araling ito, nagtatayo tayo ng utility-scale circuit na lumabas sa tinatawag naming "utility paper" na inilathala sa Nature Vol 618, 15 Hunyo 2023. Ang papel ay tumutukoy sa time evolution ng 2D transverse-field Ising model. Partikular na pinag-aaralan nila ang time dynamics ng Hamiltonian,
kung saan ang ay ang coupling ng pinakamalapit na mga spin na may at ang ay ang global transverse field. Ginagaya nila ang spin dynamics mula sa isang paunang estado sa pamamagitan ng first-order Trotter decomposition ng time-evolution operator,
kung saan ang evolution time na ay hinati sa na Trotter steps, at ang at ay mga at rotation gate, ayon sa pagkakasunod.
Nagpatakbo sila ng mga eksperimento sa isang IBM Quantum® Eagle processor, isang 127-qubit na device na may heavy-hex connectivity, na inilapat ang interactions sa lahat ng qubit at interactions para sa lahat ng edges ng coupling map. Tandaan na hindi lahat ng interactions ay maaaring ilapat nang sabay-sabay dahil sa "data dependance". Kaya naman, kino-color nila ang coupling map para pagrupuhin ang mga ito sa mga layer. Ang mga nasa iisang layer ay may parehong kulay at maaaring ilapat nang sabay-sabay.
Bukod dito, para sa kaginhawahan ng eksperimento, nagtuon sila sa kaso ng .
Ang bagong kontribusyon ng papel ay nagtatayo sila ng mga quantum circuit sa sukat na higit pa sa kaya ng statevector simulation, pinatakbo ang mga ito sa mga maingay na quantum computer, at nagtagumpay na makakuha ng mapagkakatiwalaang mga resulta. Ibig sabihin, naipakita nila ang pagiging kapaki-pakinabang ng mga maingay na quantum computer. Para magawa ito, gumamit sila ng zero-noise extrapolation (ZNE) na may probabilistic error amplification (PEA) para mabawasan ang mga error mula sa mga maingay na device.
Mula noon, tinawag namin ang mga ganitong eksperimento at circuit na "utility-scale".
1.1 Ang iyong layunin
Ang iyong layunin sa araling ito ay magtayo ng utility-scale circuit at patakbuhin ito sa isang Eagle processor. Lampas sa saklaw ng notebook na ito ang pagkuha ng mapagkakatiwalaang mga resulta, bahagi dahil ang PEA ay isang experimental na feature ng Qiskit sa oras ng pagsulat nito, at bahagi dahil ang paggamit ng ZNE na may PEA ay kukuha ng mahabang panahon.
Konkretamente, hinihiling sa iyo na itayo at patakbuhin ang circuit na katumbas ng Figure 4b ng papel, at i-plot ang iyong sariling "unmitigated" na mga punto. Makikita mo, ito ay isang 127-qubit 60-layer (20 Trotter steps) na circuit na may bilang observable.
Mukhang malaking bagay? Huwag mag-alala. Ang huling tatlong aralin ng kursong ito ay nagbibigay ng mga hakbang-hakbang na paghahanda. Para magsimula, magpapakita tayo ng mas maliit na eksperimento — itayo at patakbuhin sa isang pekeng device ang isang 27-qubit 6-layer (2 Trotter steps) na circuit na may bilang observable.
Iyon na ang panimula. Magsimula na tayong mag-explore ng utility-scale na mundo!
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime rustworkx
import qiskit
qiskit.__version__
'2.0.2'
#!pip install qiskit_ibm_runtime
#!pip install qiskit_aer
import matplotlib.pyplot as plt
import numpy as np
import rustworkx as rx
from qiskit import QuantumCircuit, transpile
from qiskit.circuit import Parameter
from qiskit.circuit.library import YGate
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import (
QiskitRuntimeService,
fake_provider,
EstimatorV2 as Estimator,
)
from qiskit_aer import AerSimulator
service = QiskitRuntimeService()
2. Paghahanda
2.1 Itayo ang RZZ(- / 2)
Una, pansinin na ang RZZ gate sa pangkalahatan ay nangangailangan ng dalawang gate.
from qiskit.circuit.library import RZZGate
θ_h = Parameter("$\\theta_h$")
qc1 = QuantumCircuit(2)
qc1.append(RZZGate(θ_h), [0, 1])
qc1.decompose(reps=1).draw("mpl")
Gaya ng nabanggit sa itaas, nagtutuon tayo sa RZZ gate na may tiyak na anggulo, - / 2, para sa eksperimentong ito. Tulad ng ipinapakita sa papel, maisasakatuparan ito gamit ang isang gate lamang.
qc2 = QuantumCircuit(2)
qc2.sdg([0, 1])
qc2.append(YGate().power(1 / 2), [1])
qc2.cx(0, 1)
qc2.append(YGate().power(1 / 2).adjoint(), [1])
qc2.draw("mpl")
Tinutukoy natin ang isang gate batay sa circuit na ito para sa hinaharap na paggamit.
rzz = qc2.to_gate(label="RZZ")
Subukan nating gamitin ang bagong-taong rzz.
qc3 = QuantumCircuit(3)
qc3.append(rzz, [0, 1])
qc3.append(rzz, [0, 2])
display(qc3.draw("mpl"))
# display(qc.decompose(reps=1).draw("mpl"))
Bago gamitin ito pa nang higit, i-verify natin ang lohikal na pagkakatulad ng qc1 (ang RZZ gate) para sa -pi/2 at ng ating bagong-taong rzz o qc2 gate:
from qiskit.quantum_info import Operator
op1 = Operator(qc1.assign_parameters([-np.pi / 2]))
op2 = Operator(qc2)
op1.equiv(op2)
True
2.2 I-color ang coupling map
Pag-aralan natin kung paano kino-color ang coupling map ng isang backend. Kailangan ito para mapangkat ang mga interaction sa mga layer.
Para magsimula, i-visualize natin ang coupling map ng isang backend. Tandaan na ang mga coupling map ay heavy-hexagonal para sa lahat ng kasalukuyang IBM Quantum device.
backend = service.least_busy(operational=True, simulator=False)
backend.coupling_map.draw()

Para ma-color ang coupling map, gumagamit tayo ng rustworkx, isang Python package para sa pagtrabaho sa mga graph at complex network. Nagbibigay ito ng maraming coloring algorithm, na lahat ay heuristic kaya hindi garantisadong makakakita ng minimal na coloring.
Gayunpaman, dahil bipartite ang mga heavy-hex graph, pipiliin natin ang graph_bipartite_edge_color, na dapat makahanap ng minimal na coloring para sa mga graph na ito.
def color_coupling_map(backend):
graph = backend.coupling_map.graph
undirected_graph = graph.to_undirected(multigraph=False)
edge_color_map = rx.graph_bipartite_edge_color(undirected_graph)
if edge_color_map is None:
edge_color_map = rx.graph_greedy_edge_color(undirected_graph)
# build a map from color to a list of edges
edge_index_map = undirected_graph.edge_index_map()
color_edges_map = {color: [] for color in edge_color_map.values()}
for edge_index, color in edge_color_map.items():
color_edges_map[color].append(
(edge_index_map[edge_index][0], edge_index_map[edge_index][1])
)
return edge_color_map, color_edges_map
Ang mga heavy-hexagonal graph ay dapat mapinturahan ng tatlong kulay. Suriin natin ito para sa coupling map sa itaas.
edge_color_map, color_edges_map = color_coupling_map(backend)
print(
f"{backend.name}, {backend.num_qubits}-qubit device, {len(color_edges_map.keys())} colors assigned."
)
ibm_strasbourg, 127-qubit device, 3 colors assigned.
Tama nga!
Para sa kasiyahan, pinturahan natin ang coupling map ayon sa nahanap na coloring, gamit ang feature ng rustworkx visualization.
color_str_map = {0: "green", 1: "red", 2: "blue"}
undirected_graph = backend.coupling_map.graph.to_undirected(multigraph=False)
for i in undirected_graph.edge_indices():
undirected_graph.get_edge_data_by_index(i)["color"] = color_str_map[
edge_color_map[i]
]
rx.visualization.graphviz_draw(
undirected_graph, method="neato", edge_attr_fn=lambda edge: {"color": edge["color"]}
)

3. Lutasin ang Trotterized time evolution ng isang 2D Ising model.
Tukuyin natin ang isang routine para magtayo ng circuit ng utility paper para sa time evolution ng 2D Ising model. Ang routine ay tumatanggap ng tatlong parameter: isang backend, isang integer na nagpapahiwatig ng bilang ng Trotter steps, at isang Boolean na nagkokontrol sa paglalagay ng barrier.
def get_utility_circuit(backend, num_steps: int, barrier: bool = False):
num_qubits = backend.num_qubits
_, color_edges_map = color_coupling_map(backend)
θ_h = Parameter("$\\theta_h$")
qc = QuantumCircuit(num_qubits)
for i in range(num_steps):
qc.rx(θ_h, range(num_qubits))
for _, edge_list in color_edges_map.items():
for edge in edge_list:
qc.append(rzz, edge)
if barrier:
qc.barrier()
return qc
Tandaan na manu-mano na nating ginawa ang qubit mapping at routing para sa itinayong circuit. Kaya naman, kapag na-transpile natin ang circuit mamaya, hindi na natin dapat hilingin sa Transpiler na gumawa ng qubit mapping at routing. Tulad ng makikita mo sa lalong madaling panahon, tatawagin natin ito na may optimization level na 1 at layout method na "trivial".
Susunod, tukuyin natin ang isang simpleng routine para makuha ang impormasyon tungkol sa itinayong circuit para sa mabilis na pagsusuri.
def get_circuit_info(qc: QuantumCircuit, reps: int = 0):
qc0 = qc.decompose(reps=reps)
return (
f"{qc0.num_qubits} qubits × {qc0.depth(lambda x: x.operation.num_qubits == 2)} layers ({qc0.depth()}-depth)"
+ ", "
+ f"""Gate breakdown: {", ".join([f"{k.upper()} {v}" for k, v in qc0.count_ops().items()])}"""
)
Subukan natin ang mga routine na ito. Dapat makita mo ang isang circuit na 27 qubit 15 layers (5 Trotter steps). Dahil ang pekeng device ay may 28 edges, dapat ay 28*5 ang bilang ng entangling gate.
backend = fake_provider.FakeTorontoV2()
num_steps = 5
qc = get_utility_circuit(backend, num_steps, True)
display(qc.draw(output="mpl", fold=-1))
print(get_circuit_info(qc, reps=0))
print(get_circuit_info(qc, reps=1))

27 qubits × 15 layers (20-depth), Gate breakdown: CIRCUIT-165 140, RX 135, BARRIER 5
27 qubits × 15 layers (60-depth), Gate breakdown: SDG 280, UNITARY 280, CX 140, R 135, BARRIER 5
4. Lutasin ang 27-qubit na bersyon ng problema.
Ipapakita natin ngayon ang mas maliit na bersyon ng utility experiment. Magtatayo tayo ng 27-qubit 6-layer (2 Trotter steps) na circuit na may bilang observable, at patakbuhin ito sa parehong AerSimulator at isang pekeng device.
Siyempre, susunod tayo sa ating four-step workflow na "Qiskit pattern," na binubuo ng Map, Optimize, Execute, at Post-Process. Konkretamente:
- I-map ang mga classical na input sa isang quantum computation.
- I-optimize ang mga circuit para sa quantum computation.
- I-execute ang mga circuit gamit ang primitives.
- I-post-process at ibalik ang mga resulta sa classical na format.
Sa sumusunod, mayroon tayong Map step para lumikha ng circuit para sa mas maliit na eksperimento. Pagkatapos, mayroon tayong isang set ng Optimize at Execute para sa AerSimulator at isa pa para sa pekeng device. Sa wakas, mayroon tayong Post-Process step para i-plot ang mga resulta.
4.1 Hakbang 1: Map
backend = fake_provider.FakeTorontoV2() # a 27 qubit fake device.
num_steps = 2
qc = get_utility_circuit(backend, num_steps)
obs = SparsePauliOp.from_sparse_list(
[("Z", [13], 1)], num_qubits=backend.num_qubits
) # Falcon
angles = [
0,
0.1,
0.2,
0.3,
0.4,
0.5,
0.6,
0.7,
0.8,
1.0,
np.pi / 2,
] # We try 11 angles for theta_h.
4.2 Mga Hakbang 2 at 3: Optimize at Execute (Simulator)
backend_sim = AerSimulator()
transpiled_qc_sim = transpile(
qc, backend_sim, optimization_level=1, layout_method="trivial"
)
transpiled_obs_sim = obs.apply_layout(layout=transpiled_qc_sim.layout)
print(get_circuit_info(qc, reps=1))
print(get_circuit_info(transpiled_qc_sim, reps=1))
27 qubits × 6 layers (23-depth), Gate breakdown: SDG 112, UNITARY 112, CX 56, R 54
27 qubits × 6 layers (16-depth), Gate breakdown: U3 80, CX 56, R 54, U1 32, U 28
Isang user ang nagpatakbo ng susunod na cell gamit ang MacBook Pro na may 2.3 GHz quad-core Intel Core i7 Processor na may 32GB 3LPDDR4X RAM, na nagpapatakbo ng macOS 14.5. Tumagal ito ng 161ms sa wall time. Magkakaiba-iba ang bawat laptop.
%%time
params = [[p] for p in angles]
estimator = Estimator(mode=backend_sim)
pub = (transpiled_qc_sim, transpiled_obs_sim, params)
result_sim = estimator.run([pub]).result()
CPU times: user 231 ms, sys: 186 ms, total: 417 ms
Wall time: 111 ms
4.3 Mga Hakbang 2 at 3: Optimize at execute (pekeng device)
backend_fake = fake_provider.FakeTorontoV2()
transpiled_qc_fake = transpile(
qc, backend_fake, optimization_level=1, layout_method="trivial"
)
transpiled_obs_fake = obs.apply_layout(layout=transpiled_qc_fake.layout)
print(get_circuit_info(qc, reps=1))
print(get_circuit_info(transpiled_qc_fake, reps=1))
27 qubits × 6 layers (23-depth), Gate breakdown: SDG 112, UNITARY 112, CX 56, R 54
27 qubits × 6 layers (49-depth), Gate breakdown: SDG 324, U1 274, H 162, CX 56, U3 14
Nang patakbuhin ng parehong user ang susunod na cell sa parehong kapaligiran, tumagal ito ng 2min 19s sa Wall Time. Ang pagpapatakbo ng circuit sa isang pekeng device ay nagsasangkot ng maingay na simulation na mas matagal kaysa sa eksaktong simulation. Inirerekomenda naming huwag magpatakbo ng mas malaking circuit (tulad ng 27-qubit 9 layers na may 3 Trotter steps) sa isang pekeng device.
%%time
params = [[p] for p in angles]
estimator = Estimator(mode=backend_fake)
pub = (transpiled_qc_fake, transpiled_obs_fake, params)
result_fake = estimator.run([pub]).result()
CPU times: user 4min 42s, sys: 9.35 s, total: 4min 51s
Wall time: 38.3 s
4.4 Hakbang 4: Post-process
Ini-plot natin ang mga resulta mula sa eksaktong at maingay na simulation. Makikita mo ang matinding epekto ng ingay sa FakeToronto.
plt.plot(angles, result_fake[0].data.evs, "o", label="Fake Device")
plt.plot(angles, result_sim[0].data.evs, "o", label="AerSimulator")
plt.xlabel("$\\mathrm{R_x}$ angle $\\theta_h$")
plt.title("$\\langle Z_{13} \\rangle$")
plt.legend()
plt.show()
5. Lutasin ang 127-qubit na bersyon ng problema
Ang iyong layunin ay patakbuhin ang utility-scale experiment gaya ng nabanggit sa simula. Lilikha at magpapatakbo ka ng isang 127-qubit at 60-layer (20 Trotter steps) na circuit na may bilang observable. Inirerekomenda naming subukan mo itong gawin nang mag-isa, gamit ang code para sa 27-qubit na bersyon kung kinakailangan. Ngunit narito na rin ang solusyon.
Solusyon:
5.1 Hakbang 1: Map
# backend_map = service.backend("ibm_brisbane")
backend_map = service.least_busy(operational=True, simulator=False)
num_steps = 20
qc = get_utility_circuit(backend_map, num_steps)
obs = SparsePauliOp.from_sparse_list(
[("Z", [62], 1)], num_qubits=backend_map.num_qubits
) # Eagle
angles = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0, np.pi / 2]
5.2 Mga Hakbang 2 at 3: Optimize at execute
Tandaan na ang coupling map ng Eagle processor ay may 144 edges.
# backend = service.backend("ibm_brisbane")
backend = backend_map
transpiled_qc = transpile(qc, backend, optimization_level=1, layout_method="trivial")
transpiled_obs = obs.apply_layout(layout=transpiled_qc.layout)
print(get_circuit_info(qc, reps=1))
print(get_circuit_info(transpiled_qc))
156 qubits × 60 layers (221-depth), Gate breakdown: SDG 7040, UNITARY 7040, CX 3520, R 3120
156 qubits × 60 layers (201-depth), Gate breakdown: RZ 11933, SX 6240, CZ 3520
params = [[p] for p in angles]
estimator = Estimator(mode=backend)
pub = (transpiled_qc, transpiled_obs, params)
job = estimator.run([pub])
job_id = job.job_id()
print(f"job id={job_id}")
job id=d1479n6qf56g0081sxa0
5.3 Post-process
Ibinibigay namin ang mga halaga para sa "mitigated" na mga punto sa Figure 4b ng utility paper. I-plot ang mga ito kasama ang iyong mga resulta.
result_paper = [
1.0171,
1.0044,
0.9563,
0.9602,
0.8394,
0.8120,
0.5466,
0.4556,
0.1953,
0.0141,
0.0117,
]
# REPLACE WITH YOUR OWN JOB ID
job = service.job(job_id)
plt.plot(angles, job.result()[0].data.evs, "o", label=f"{job.backend().name}")
plt.plot(angles, result_paper, "o", label="Utility Paper")
plt.xlabel("$\\mathrm{R_x}$ angle $\\theta_h$")
plt.title("$\\langle Z_{62} \\rangle$")
plt.legend()
plt.show()
Katulad ba ang iyong mga resulta sa "unmitigated" sa Figure 4b? Maaaring lubhang magkaiba ang mga ito, depende sa device at sa kondisyon nito sa oras ng eksperimento. Huwag mag-alala tungkol sa mga resulta mismo. Ang susuriin natin ay kung tama ang iyong coding. Kung nagawa mo nang tama, congratulations — nakarating ka na sa simula ng utility era.
Tulad ng sa Utility paper, ang mga siyentipiko sa buong mundo ay nagpakita ng malaking katalinuhan sa pagkuha ng makabuluhang mga resulta kahit na may ingay. Ang panghuling layunin ng kolektibong pagsisikap na ito ay ang quantum advantage: isang estado kung saan ang mga quantum computer ay makalutas ng ilang mga problemang kapaki-pakinabang sa industriya nang mas mabilis, may mas mataas na katumpakan, o mas mura kaysa sa mga klasikal na computer. Hindi ito malamang na isang solong pangyayari, kundi isang panahon kung saan ang klasikal na pagpaparami ng mga quantum na resulta ay unti-unting nagiging mas mahirap, hanggang sa puntong ang predwentahe ng quantum ay nagiging kritikal na mahalaga. Isang bagay ang malinaw tungkol sa quantum advantage: maaabot lamang natin ito sa pamamagitan ng mga utility-scale na eksperimento. Kung ang kursong ito ay magtutulak sa iyo na sumali sa paghahanap na ito, na puno ng hamon at kasiyahan, magiging labis kaming masaya.
Sanggunian
- Kim, Y., Eddins, A., Anand, S. et al. Evidence for the utility of quantum computing before fault tolerance. Nature 618, 500–505 (2023). https://doi.org/10.1038/s41586-023-06096-3