Menggabungkan semuanya dengan Qiskit Runtime
Ringkasan​
Victoria Lipinska memberikan rekap akhir dari apa yang telah kita pelajari sejauh ini.
Referensi​
Artikel-artikel berikut dirujuk dalam video di atas.
- Quantum Chemistry in the Age of Quantum Computing, Cao, et al.
- Quantum computational chemistry, McArdle, et al.
VQE dengan pola Qiskit​
Kita memiliki semua komponen yang diperlukan untuk kalkulasi VQE:
- Hamiltonian
- Ansatz
- Optimizer klasik
Sekarang kita hanya perlu menyatukannya dalam kerangka pola Qiskit.
Langkah 1: Petakan masukan klasik ke masalah kuantum​
Seperti yang dinyatakan sebelumnya, kita akan mengasumsikan di sini bahwa Hamiltonian yang diformat dengan tepat dari masalah yang diminati telah dibuat. Jika kamu memiliki pertanyaan tentang itu, lihat pelajaran tentang Hamiltonians untuk panduan. Blok kode di bawah ini menyiapkan komponen yang dijelaskan dalam pelajaran sebelumnya. Di sini kita telah memilih untuk memodelkan H2 karena Hamiltoniannya cukup kompak untuk ditulis.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime scipy
# General imports
import numpy as np
from qiskit.quantum_info import SparsePauliOp
# Hamiltonian obtained from a previous lesson
H = SparsePauliOp(
[
"IIII",
"IIIZ",
"IZII",
"IIZI",
"ZIII",
"IZIZ",
"IIZZ",
"ZIIZ",
"IZZI",
"ZZII",
"ZIZI",
"YYYY",
"XXYY",
"YYXX",
"XXXX",
],
coeffs=[
-0.09820182 + 0.0j,
-0.1740751 + 0.0j,
-0.1740751 + 0.0j,
0.2242933 + 0.0j,
0.2242933 + 0.0j,
0.16891402 + 0.0j,
0.1210099 + 0.0j,
0.16631441 + 0.0j,
0.16631441 + 0.0j,
0.1210099 + 0.0j,
0.17504456 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
],
)
nuclear_repulsion = 0.7199689944489797
Kita memilih circuit efficient_su2, dan optimizer COBYLA, untuk memulai.
# Pre-defined ansatz circuit
from qiskit.circuit.library import efficient_su2
# SciPy minimizer routine
from scipy.optimize import minimize
# Plotting functions
# Random initial state and efficient_su2 ansatz
ansatz = efficient_su2(H.num_qubits, su2_gates=["rx"], entanglement="linear", reps=1)
x0 = 2 * np.pi * np.random.random(ansatz.num_parameters)
print(ansatz.decompose().depth())
ansatz.decompose().draw("mpl")
5
Sekarang kita membangun fungsi biaya kita. Ini jelas terkait dengan Hamiltonian, tetapi berbeda karena Hamiltonian adalah operator, dan kita menginginkan fungsi yang mengembalikan nilai ekspektasi dari operator tersebut, menggunakan Estimator. Tentu saja, ini dicapai dengan menggunakan ansatz dan parameter variasional, sehingga semuanya muncul sebagai argumen. Di bawah ini, kita mendefinisikan versi yang sedikit berbeda untuk digunakan pada perangkat keras nyata atau simulator.
def cost_func(params, ansatz, H, estimator):
pub = (ansatz, [H], [params])
result = estimator.run(pubs=[pub]).result()
energy = result[0].data.evs[0]
return energy
# def cost_func_sim(params, ansatz, H, estimator):
# energy = estimator.run(ansatz, H, parameter_values=params).result().values[0]
# return energy
Langkah 2: Optimalkan masalah untuk eksekusi kuantum.​
Kita ingin kode kita berjalan seefisien mungkin pada perangkat keras yang kita gunakan. Jadi kita harus memilih Backend untuk memulai langkah optimisasi. Kode di bawah ini memilih Backend yang paling tidak sibuk yang tersedia untukmu.
# To run on hardware, select the backend with the fewest number of jobs in the queue
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService(channel="ibm_quantum_platform")
backend = service.least_busy(operational=True, simulator=False)
backend.name
Mengoptimalkan circuit untuk dijalankan pada Backend nyata adalah topik yang kaya dan kritis. Tetapi ini tidak spesifik untuk VQE. Untuk saat ini, kita hanya akan mengingatkanmu tentang dua istilah penting:
- optimization_level: Ini menjelaskan seberapa baik circuit disesuaikan dengan tata letak Backend yang dipilih. Tingkat optimisasi terendah hanya melakukan minimum yang diperlukan agar circuit berjalan di perangkat; ia memetakan qubit circuit ke qubit perangkat dan menambahkan gate swap untuk memungkinkan semua operasi dua-qubit. Tingkat optimisasi tertinggi jauh lebih cerdas dan menggunakan banyak trik untuk mengurangi jumlah gate secara keseluruhan. Karena gate multi-qubit memiliki tingkat kesalahan yang tinggi dan qubit terdekoherensi seiring waktu, circuit yang lebih pendek seharusnya memberikan hasil yang lebih baik.
- Dynamical Decoupling: Kita dapat menerapkan urutan gate pada qubit yang idle. Ini membatalkan beberapa interaksi yang tidak diinginkan dengan lingkungan.
Konsultasikan dokumentasi tertaut untuk informasi lebih lanjut tentang mengoptimalkan circuit. Kode di bawah ini menghasilkan manajer pass menggunakan preset pass manager dari
qiskit.transpiler.
from qiskit.transpiler import PassManager
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
ConstrainedReschedule,
)
from qiskit.circuit.library import XGate
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
pm.scheduling = PassManager(
[
ALAPScheduleAnalysis(target=target),
ConstrainedReschedule(
acquire_alignment=target.acquire_alignment,
pulse_alignment=target.pulse_alignment,
target=target,
),
PadDynamicalDecoupling(
target=target,
dd_sequence=[XGate(), XGate()],
pulse_alignment=target.pulse_alignment,
),
]
)
# Use the pass manager and draw the resulting circuit
ansatz_isa = pm.run(ansatz)
ansatz_isa.draw(output="mpl", idle_wires=False, style="iqp")
Kita juga harus menerapkan karakteristik tata letak perangkat pada Hamiltonian.
hamiltonian_isa = H.apply_layout(ansatz_isa.layout)
hamiltonian_isa
SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYXXII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXXXII'],
coeffs=[-0.09820182+0.j, -0.1740751 +0.j, -0.1740751 +0.j, 0.2242933 +0.j,
0.2242933 +0.j, 0.16891402+0.j, 0.1210099 +0.j, 0.16631441+0.j,
0.16631441+0.j, 0.1210099 +0.j, 0.17504456+0.j, 0.04530451+0.j,
0.04530451+0.j, 0.04530451+0.j, 0.04530451+0.j])
Langkah 3: Eksekusi menggunakan Qiskit Primitives.​
Sebelum kita mengeksekusi pada perangkat keras yang dipilih, adalah ide yang baik untuk menggunakan simulator untuk debugging awal, dan kadang-kadang untuk perkiraan kesalahan. Untuk alasan tersebut, kita secara singkat menunjukkan cara menjalankan VQE pada simulator. Tetapi penting untuk dicatat bahwa tidak ada komputer klasik, simulator, atau GPU yang dapat secara akurat mensimulasikan fungsionalitas penuh komputer kuantum 127-qubit yang sangat terjerat. Dalam era utilitas kuantum saat ini, simulator akan memiliki penggunaan yang terbatas.
Ingat bahwa untuk setiap pilihan parameter dalam variational circuit, nilai ekspektasi harus dihitung (karena itulah nilai yang diminimalkan). Seperti yang mungkin sudah kamu duga, cara paling efisien untuk melakukannya adalah menggunakan primitif Qiskit, Estimator. Kita akan mulai dengan menggunakan simulator lokal, yang akan mengharuskan kita menggunakan versi lokal dari Estimator yang disebut BackendEstimator.
Mempertahankan Backend nyata yang kita gunakan untuk optimisasi, kita dapat mengimpor model perilaku kebisingan perangkat tersebut untuk kemudian digunakan dengan simulator lokal pilihan kita. Di sini, kita akan menggunakan aer_simulator_statevector.
# We will start by using a local simulator
from qiskit_aer import AerSimulator
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit.primitives import BackendEstimatorV2
# generate a simulator that mimics the real quantum system
backend_sim = AerSimulator.from_backend(backend)
estimator = BackendEstimatorV2(backend=backend_sim)
Akhirnya saatnya mengimplementasikan VQE, meminimalkan fungsi biaya menggunakan Hamiltonian, ansatz, optimizer klasik yang dipilih, dan BackendEstimator kita, berdasarkan Backend nyata yang kita pilih untuk penggunaan selanjutnya. Perhatikan bahwa di sini kita telah memilih angka yang relatif kecil untuk iterasi maksimum. Ini karena kita hanya menggunakan simulator untuk debugging. Langkah optimisasi VQE seringkali memerlukan ratusan iterasi untuk konvergen.
res = minimize(
cost_func,
x0,
args=(ansatz_isa, hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 10, "disp": True},
)
print(getattr(res, "fun") - nuclear_repulsion)
print(res)
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 10 Least value of F = -0.11556938907226563
The corresponding X is:
[4.11796514 4.52126324 0.69570423 4.12781503 6.55507846 1.80713073
0.9645473 6.23812214]
-0.8355383835212453
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.11556938907226563
x: [ 4.118e+00 4.521e+00 6.957e-01 4.128e+00 6.555e+00
1.807e+00 9.645e-01 6.238e+00]
nfev: 10
maxcv: 0.0
Kode ini dievaluasi dengan benar, meskipun tidak konvergen, yang kita harapkan. Kita akan melanjutkan menjalankan kalkulasi pada perangkat keras nyata, dan kemudian mendiskusikan hasilnya. Untuk Backend nyata, kita akan menggunakan Qiskit Runtime Estimator. Kita akan ingin mengeksekusi ini di dalam sesi Qiskit Runtime dan kita umumnya ingin menentukan opsi untuk sesi tersebut.
from qiskit_ibm_runtime import QiskitRuntimeService, Session
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.options import EstimatorOptions
Di antara hal-hal lain, menggunakan sesi berarti pekerjaan kita hanya akan menunggu dalam antrian sekali, untuk memulai. Iterasi selanjutnya dari optimizer klasik tidak akan antri. Dalam sesi, kita dapat mengatur tingkat resiliensi dan optimisasi. Alat-alat ini cukup penting sehingga kita menyertakan ulasan singkat tentang masing-masing dan pentingnya dalam VQE, dengan tautan untuk mempelajari lebih lanjut:
- Sesi Runtime: VQE pada dasarnya bersifat iteratif, dengan optimizer klasik memilih parameter variasional baru, sehingga gate baru digunakan, dalam setiap percobaan selanjutnya. Tanpa menggunakan sesi, ini bisa menghasilkan waktu antri tambahan antara setiap circuit percobaan. Merangkum kalkulasi VQE di dalam sesi menghasilkan hanya satu antrian awal sebelum pekerjaan dimulai, tetapi tidak ada waktu antri tambahan antara langkah variasional. Strategi ini sudah digunakan dalam contoh pelajaran sebelumnya, tetapi mungkin memainkan peran yang lebih penting saat memvariasikan geometri. Untuk informasi lebih lanjut tentang sesi, tinjau dokumentasi mode eksekusi.
- Optimisasi bawaan Estimator: Di Estimator ada opsi bawaan untuk mengoptimalkan kalkulasi. Dalam banyak konteks (termasuk Estimator), pengaturan dibatasi pada 0 dan 1, dengan 0 menunjukkan tidak ada optimisasi, dan 1 (default) menunjukkan beberapa optimisasi circuit ke perangkat keras yang dipilih. Beberapa konteks lain memungkinkan pengaturan 0, 1, 2, atau 3. Untuk informasi lebih lanjut tentang metode spesifik yang digunakan dalam pengaturan berbeda, lihat dokumentasi. Di sini, kita sebenarnya akan mengatur optimisasi ke 0, dan menggunakan 'skip_transpilation = true', karena kita sudah mentranspilasi circuit kita menggunakan pass manager di atas, di bagian optimisasi.
- Resiliensi bawaan Estimator: Seperti dengan optimisasi, Estimator memiliki pengaturan bawaan untuk resiliensi terhadap kesalahan, yang bersesuaian dengan pendekatan yang berbeda terhadap mitigasi kesalahan. Untuk mempelajari tentang pengaturan tingkat resiliensi, lihat dokumentasi.
Layak dicatat bahwa mitigasi kesalahan memainkan peran yang nuansif dalam konvergensi kalkulasi VQE. Optimizer klasik mencari ruang parameter untuk parameter-parameter yang meminimalkan energi. Ketika kamu sangat jauh dari parameter optimal, gradien yang curam mungkin terlihat oleh optimizer klasik bahkan dengan adanya kesalahan. Tetapi saat kalkulasi konvergen dan kamu mendekati nilai optimal, gradien menjadi lebih kecil, dan lebih mudah terhapus oleh kesalahan. Berapa banyak mitigasi kesalahan yang ingin kamu gunakan? Pada titik mana dalam konvergensi? Ini adalah pilihan yang harus kamu buat untuk kasus penggunaan khususmu.
Untuk hardware run pertama ini, kita telah mengatur resiliensi ke 0 untuk memfasilitasi run yang relatif cepat. Untuk aplikasi serius apa pun, kamu akan ingin menggunakan mitigasi kesalahan. Perhatikan bahwa dalam sel di bawah ini ada dua set opsi: (1) opsi untuk sesi Runtime, yang kita beri nama "session_options", dan (2) opsi untuk optimizer klasik, yang disebut "options" di sini.
estimator_options = EstimatorOptions(resilience_level=0, default_shots=2000)
with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)
res = minimize(
cost_func,
x0,
args=(ansatz_isa, hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 10, "disp": True},
)
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 10 Least value of F = -0.11691688904
The corresponding X is:
[5.11796514 5.52126324 0.69570423 5.12781503 6.55507846 1.80713073
1.9645473 6.23812214]
Kamu bisa melihat kemajuan pekerjaanmu di IBM Quantum® Platform di bagian Workloads.
print(getattr(res, "fun") - nuclear_repulsion)
print(res)
-0.8368858834889796
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.11691688904
x: [ 5.118e+00 5.521e+00 6.957e-01 5.128e+00 6.555e+00
1.807e+00 1.965e+00 6.238e+00]
nfev: 10
maxcv: 0.0
Langkah 4: Pasca-proses, kembalikan hasil dalam format klasik.​
Mari kita sejenak memastikan kita memahami hasil-hasil ini. Keluaran "fun" adalah nilai minimum yang kita peroleh untuk fungsi biaya (tidak harus nilai terakhir yang dihitung). Ini adalah total energi, termasuk repulsi nuklir positif, itulah mengapa kita juga mendefinisikan electron_energy.
Dalam kasus di atas, kita mendapat pesan bahwa jumlah maksimum evaluasi fungsi telah terlampaui, dan bahwa jumlah evaluasi fungsi (nfev) adalah 10. Ini hanya berarti bahwa kriteria konvergensi lain untuk optimisasi tidak terpenuhi; dengan kata lain, tidak ada alasan untuk berpikir kita menemukan energi ground state. Ini juga merupakan arti dari success yang menjadi "False".
Akhirnya, kita memiliki x. Ini adalah vektor parameter variasional. Ini adalah parameter yang digunakan dalam kalkulasi yang menghasilkan fungsi biaya minimum (nilai ekspektasi energi). Delapan nilai ini bersesuaian dengan delapan sudut rotasi dalam gate-gate dalam ansatz yang mengambil sudut rotasi variabel.
Selamat! Kamu telah menjalankan kalkulasi VQE pada IBM Quantum QPU!
Dalam pelajaran berikutnya, kita akan melihat cara menyesuaikan alur kerja ini untuk menyertakan variabel dalam Hamiltonianmu. Dalam konteks masalah kimia kuantum, ini mungkin berarti memvariasikan geometri untuk menentukan bentuk molekul atau situs pengikatan.
import qiskit
import qiskit_ibm_runtime
print(qiskit.version.get_version_info())
print(qiskit_ibm_runtime.version.get_version_info())
2.1.0
0.40.1