Eksperimen berskala utiliti I
Tamiya Onodera (5 Julai 2024)
Muat turun pdf kuliah asal. Perlu diingat bahawa beberapa petikan kod mungkin telah lapuk kerana ia adalah imej statik.
Anggaran masa QPU untuk menjalankan eksperimen ini ialah 45 saat.
1. Pengenalan kepada kertas utiliti
Dalam pelajaran ini, kita jalankan litar berskala utiliti yang muncul dalam apa yang kami panggil secara tidak rasmi "kertas utiliti" yang diterbitkan dalam Nature Vol 618, 15 Jun 2023. Kertas ini membahas evolusi masa model Ising medan melintang 2D. Secara khususnya, mereka mengkaji dinamik masa Hamiltonian,
di mana ialah gandingan spin jiran terdekat dengan dan ialah medan melintang global. Mereka mensimulasikan dinamik spin daripada keadaan awal menggunakan penguraian Trotter peringkat pertama bagi operator evolusi masa,
di mana masa evolusi dipecahkan kepada langkah Trotter dan serta masing-masing ialah Gate putaran dan .
Mereka menjalankan eksperimen pada pemproses IBM Quantum® Eagle, iaitu peranti 127-Qubit dengan ketersambungan heks berat, menggunakan interaksi pada semua Qubit dan interaksi untuk semua tepi peta gandingan. Perlu diingat bahawa semua interaksi tidak boleh digunakan serentak kerana "ketergantungan data". Oleh itu, mereka mewarnakan peta gandingan untuk mengumpulkan interaksi ke dalam lapisan. Interaksi dalam satu lapisan diberi warna yang sama dan boleh digunakan secara selari.
Selain itu, untuk memudahkan eksperimen, mereka menumpukan pada kes .
Sumbangan baharu dalam kertas ini ialah mereka membina litar kuantum pada skala melebihi simulasi vektor keadaan, menjalankannya pada komputer kuantum yang bising, dan berjaya mengekstrak keputusan yang boleh dipercayai. Iaitu, mereka menunjukkan kegunaan komputer kuantum yang bising. Dalam proses itu, mereka menggunakan extrapolasi sifar hingar (ZNE) dengan amplifikasi ralat kebarangkalian (PEA) untuk mengurangkan ralat daripada peranti yang bising.
Sejak itu, kami memanggil eksperimen dan litar sedemikian sebagai "berskala utiliti".
1.1 Matlamat anda
Matlamat kamu dalam pelajaran ini ialah membina litar berskala utiliti dan menjalankannya pada pemproses Eagle. Adalah di luar skop buku nota ini untuk mengekstrak keputusan yang boleh dipercayai, sebahagiannya kerana PEA ialah ciri eksperimental Qiskit pada masa penulisan ini dan sebahagiannya kerana menggunakan ZNE dengan PEA memerlukan masa yang agak lama.
Secara konkrit, kamu diminta untuk membina dan menjalankan litar yang sepadan dengan Rajah 4b dalam kertas tersebut, dan memplot titik "tanpa mitigasi" sendiri. Seperti yang dapat dilihat, ia adalah litar 127-Qubit 60-lapisan (20 langkah Trotter) dengan sebagai boleh cerapan.
Kedengaran besar? Jangan risau. Tiga pelajaran terakhir kursus ini menyediakan batu loncatan. Untuk bermula, kita akan menunjukkan eksperimen berskala lebih kecil iaitu membina dan menjalankan pada peranti palsu litar 27-Qubit 6-lapisan (2 langkah Trotter) dengan sebagai boleh cerapan.
Itu sahaja untuk pengenalan. Jom kita mulakan pengembaraan berskala utiliti!
# 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. Persediaan
2.1 Bina RZZ(- / 2)
Pertama, perhatikan bahawa Gate RZZ secara umum memerlukan dua 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")
Seperti yang disebutkan di atas, kita menumpukan pada Gate RZZ dengan sudut tertentu, - / 2, untuk eksperimen ini. Seperti yang ditunjukkan dalam kertas tersebut, ia boleh direalisasikan dengan hanya satu Gate .
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")
Kita takrifkan sebuah Gate berdasarkan Circuit ini untuk rujukan masa hadapan.
rzz = qc2.to_gate(label="RZZ")
Jom kita cuba gunakan rzz yang baru ditakrifkan ini.
qc3 = QuantumCircuit(3)
qc3.append(rzz, [0, 1])
qc3.append(rzz, [0, 2])
display(qc3.draw("mpl"))
# display(qc.decompose(reps=1).draw("mpl"))
Sebelum menggunakannya lebih lanjut, mari kita sahkan kesetaraan logik qc1 (Gate RZZ) untuk -pi/2 dan Gate rzz atau qc2 yang baru ditakrifkan:
from qiskit.quantum_info import Operator
op1 = Operator(qc1.assign_parameters([-np.pi / 2]))
op2 = Operator(qc2)
op1.equiv(op2)
True
2.2 Warnakan peta gandingan
Jom kita kaji cara mewarnakan peta gandingan sebuah Backend. Ini diperlukan untuk mengumpulkan interaksi ke dalam lapisan.
Untuk memulakan, jom kita visualkan peta gandingan sebuah Backend. Perhatikan bahawa peta gandingan adalah berbentuk heks berat untuk semua peranti IBM Quantum semasa.
backend = service.least_busy(operational=True, simulator=False)
backend.coupling_map.draw()

Untuk mewarnakan peta gandingan, kita gunakan rustworkx, iaitu pakej Python untuk bekerja dengan graf dan rangkaian kompleks. Ia menyediakan pelbagai algoritma pewarnaan, yang semuanya bersifat heuristik dan oleh itu tidak dijamin untuk mencari pewarnaan minimum.
Walau bagaimanapun, memandangkan graf heks berat adalah dwi-bahagian, kita pilih graph_bipartite_edge_color, yang sepatutnya mencari pewarnaan minimum untuk graf-graf ini.
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
Graf heks berat sepatutnya diwarnakan dengan tiga warna. Jom kita semak ini untuk peta gandingan di atas.
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.
Ya, betul!
Untuk keseronokan, jom kita warnakan peta gandingan mengikut pewarnaan yang diperoleh, menggunakan ciri visualisasi rustworkx.
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. Selesaikan evolusi masa Trotterized bagi model Ising 2D.
Mari kita definisikan satu rutin untuk membina Circuit bagi kertas utility bagi evolusi masa model Ising 2D. Rutin ini mengambil tiga parameter: sebuah backend, integer yang menunjukkan bilangan langkah Trotter, dan Boolean yang mengawal penyisipan halangan.
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
Sila ambil perhatian bahawa kita telah melakukan pemetaan dan penghalaan Qubit secara manual untuk Circuit yang dibina. Oleh itu, semasa kita mentranspil Circuit nanti, kita tidak (tidak sepatutnya) meminta Transpiler melakukan pemetaan dan penghalaan Qubit. Seperti yang akan anda lihat tidak lama lagi, kita memanggilnya dengan tahap pengoptimuman 1 dan kaedah susun atur sebagai "trivial".
Seterusnya kita definisikan satu rutin mudah untuk mendapatkan maklumat tentang Circuit yang dibina bagi semakan pantas.
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()])}"""
)
Mari kita latih rutin-rutin ini. Anda seharusnya melihat Circuit 27 Qubit 15 lapisan (5 langkah Trotter). Memandangkan peranti palsu mempunyai 28 tepi, sepatutnya ada 28*5 Gate pembelit.
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. Selesaikan versi 27-Qubit bagi masalah ini.
Kita kini menunjukkan versi berskala lebih kecil bagi eksperimen utility. Kita membina Circuit 27 Qubit 6 lapisan (2 langkah Trotter) dengan sebagai observable, dan menjalankannya pada AerSimulator dan peranti palsu.
Tentu saja, kita mengikuti aliran kerja empat langkah kita, "corak Qiskit", yang terdiri daripada Peta, Optima, Laksana, dan Pasca-Proses. Lebih konkrit:
- Petakan input klasik kepada pengiraan kuantum.
- Optimumkan Circuit untuk pengiraan kuantum.
- Laksanakan Circuit menggunakan primitif.
- Pasca-proses dan pulangkan hasil dalam format klasik.
Dalam bahagian berikut, kita ada langkah Peta untuk mencipta Circuit bagi eksperimen berskala lebih kecil. Kemudian kita ada satu set Optima dan Laksana untuk AerSimulator dan satu lagi untuk peranti palsu. Akhirnya, kita ada langkah Pasca-Proses untuk memplot hasil.
4.1 Langkah 1: Peta
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 Langkah 2 dan 3: Optimumkan dan Laksana (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
Seorang pengguna menjalankan sel seterusnya menggunakan MacBook Pro dengan pemproses Intel Core i7 2.3 GHz quad-core dilengkapi RAM 32GB 3LPDDR4X, yang menjalankan macOS 14.5. Ia mengambil masa 161ms dalam masa dinding. Setiap laptop akan sedikit berbeza.
%%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 Langkah 2 dan 3: Optimumkan dan laksana (peranti palsu)
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
Apabila pengguna yang sama menjalankan sel seterusnya dengan persekitaran yang sama seperti di atas, ia mengambil masa 2 minit 19 saat dalam Masa Dinding. Melaksanakan Circuit pada peranti palsu menggunakan simulasi berbising yang mengambil masa jauh lebih lama daripada simulasi tepat. Kami mengesyorkan anda tidak melaksanakan Circuit yang lebih besar (seperti Circuit 27-Qubit 9 lapisan dengan 3 langkah Trotter) pada peranti palsu.
%%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 Langkah 4: Pasca-proses
Kita memplot hasil daripada simulasi tepat dan berbising. Anda dapat melihat kesan teruk bunyi pada 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. Selesaikan versi 127-Qubit bagi masalah ini
Matlamat anda adalah untuk menjalankan eksperimen berskala utility seperti yang disebutkan pada awalnya. Anda akan mencipta dan melaksanakan Circuit 127 Qubit dan 60 lapisan (20 langkah Trotter) dengan sebagai observable. Kami mengesyorkan anda cuba melakukan ini sendiri, menggunakan kod untuk versi 27-Qubit apabila sesuai. Tetapi penyelesaiannya disediakan di sini.
Penyelesaian:
5.1 Langkah 1: Peta
# 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 Langkah 2 dan 3: Optimumkan dan laksana
Kita perhatikan bahawa peta gandingan pemproses Eagle mempunyai 144 tepi.
# 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 Pasca-proses
Kita menyediakan nilai untuk titik "yang telah dikurangkan kesalahannya" dalam Rajah 4b kertas utility. Plot nilai-nilai ini bersama hasil anda.
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()
Adakah hasil anda serupa dengan "yang tidak dikurangkan kesalahannya" dalam Rajah 4b? Ia mungkin sangat berbeza, bergantung pada peranti dan keadaannya semasa eksperimen. Jangan bimbang tentang hasil itu sendiri. Apa yang akan kita semak ialah sama ada anda telah melakukan pengekodan dengan betul. Jika anda telah melakukannya, tahniah, anda telah mencapai garis permulaan era utility.
Seperti dalam kertas Utility, para saintis di seluruh dunia telah menunjukkan kreativiti yang luar biasa untuk mengekstrak hasil yang bermakna walaupun dalam kehadiran bunyi. Matlamat akhir usaha bersama ini ialah kelebihan kuantum: suatu keadaan di mana komputer kuantum dapat menyelesaikan beberapa masalah yang berguna dalam industri dengan lebih pantas, dengan ketepatan lebih tinggi, atau lebih murah berbanding komputer klasik. Ini berkemungkinan bukan peristiwa tunggal, tetapi lebih kepada suatu era di mana penghasilan semula klasik bagi hasil kuantum mengambil masa yang semakin lama, sehingga pada satu ketika masa unggul kuantum itu menjadi sangat penting. Satu perkara yang jelas tentang kelebihan kuantum: kita hanya boleh sampai ke sana melalui eksperimen berskala utility. Jika kursus ini mengakibatkan anda menyertai pencarian ini, yang penuh cabaran dan keseronokan, kami akan sangat gembira.
Rujukan
- 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