Mengurangi error Trotter pada dinamika Hamiltonian dengan formula multi-produk
Di notebook ini, kamu akan belajar cara menggunakan Multi-Product Formula (MPF) untuk mendapatkan error Trotter yang lebih kecil pada observable kita dibandingkan error yang dihasilkan oleh Circuit Trotter terdalam yang benar-benar akan kita eksekusi. Kamu akan melakukannya dengan mengikuti langkah-langkah dalam sebuah pola Qiskit:
- Langkah 1: Petakan ke masalah kuantum
- Inisialisasi Hamiltonian masalah kita
- Gunakan MPF untuk membangkitkan Circuit evolusi waktu Trotterized
- Langkah 2: Optimalkan masalah
- Di sini kita melakukan transpilasi Circuit kita untuk sebuah GenericBackendV2
- Langkah 3: Jalankan eksperimen
- Gunakan StatevectorEstimator untuk kemudahan di notebook ini
- Langkah 4: Rekonstruksi hasil
- Hitung nilai ekspektasi MPF
Langkah 1: Petakan ke masalah kuantumβ
1a: Menyiapkan Hamiltonian kitaβ
Kita menggunakan model Ising pada garis 10 situs:
di mana adalah kekuatan kopling antara dua situs dan adalah medan magnet eksternal. Paket qiskit_addon_utils menyediakan berbagai fungsi yang dapat digunakan ulang untuk berbagai keperluan.
Modul qiskit_addon_utils.problem_generators menyediakan fungsi-fungsi untuk membangkitkan Hamiltonian mirip Heisenberg pada graf konektivitas tertentu. Graf ini bisa berupa rustworkx.PyGraph atau CouplingMap sehingga mudah digunakan dalam alur kerja berbasis Qiskit.
Berikut ini, kita membuat garis sederhana dari 10 Qubit menggunakan metode CouplingMap.from_line.
# Added by doQumentation β required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-mpf qiskit-addon-utils rustworkx scipy
from qiskit.transpiler import CouplingMap
# Generate some coupling map to use for this example
coupling_map = CouplingMap.from_line(10, bidirectional=False)
from rustworkx.visualization import graphviz_draw
graphviz_draw(coupling_map.graph, method="circo")
Selanjutnya, kita membangkitkan SparsePauliOp pada konektivitas yang diberikan dengan konstanta yang diinginkan.
from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian
# Get a qubit operator describing the Ising field model
hamiltonian = generate_xyz_hamiltonian(
coupling_map,
coupling_constants=(0.0, 0.0, 1.0),
ext_magnetic_field=(0.4, 0.0, 0.0),
)
print(hamiltonian)
SparsePauliOp(['IIIIIIIZZI', 'IIIIIZZIII', 'IIIZZIIIII', 'IZZIIIIIII', 'IIIIIIIIZZ', 'IIIIIIZZII', 'IIIIZZIIII', 'IIZZIIIIII', 'ZZIIIIIIII', 'IIIIIIIIIX', 'IIIIIIIIXI', 'IIIIIIIXII', 'IIIIIIXIII', 'IIIIIXIIII', 'IIIIXIIIII', 'IIIXIIIIII', 'IIXIIIIIII', 'IXIIIIIIII', 'XIIIIIIIII'],
coeffs=[1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j,
1. +0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j,
0.4+0.j, 0.4+0.j, 0.4+0.j])
Observable yang akan kita ukur adalah total magnetisasi yang dapat kita bangun dengan sederhana seperti di bawah ini:
from qiskit.quantum_info import SparsePauliOp
L = coupling_map.size()
observable = SparsePauliOp.from_sparse_list([("Z", [i], 1 / L / 2) for i in range(L)], num_qubits=L)
print(observable)
SparsePauliOp(['IIIIIIIIIZ', 'IIIIIIIIZI', 'IIIIIIIZII', 'IIIIIIZIII', 'IIIIIZIIII', 'IIIIZIIIII', 'IIIZIIIIII', 'IIZIIIIIII', 'IZIIIIIIII', 'ZIIIIIIIII'],
coeffs=[0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j,
0.05+0.j, 0.05+0.j, 0.05+0.j])
1b: Formula Multi-Produkβ
MPF mengurangi error Trotter pada dinamika Hamiltonian melalui kombinasi berbobot dari beberapa eksekusi Circuit.
Untuk lebih konkretnya, kita mendefinisikan MPF sebagai:
di mana adalah koefisien pembobotan kita, adalah matriks densitas yang bersesuaian dengan keadaan murni yang diperoleh dengan mengevolusi keadaan awal menggunakan formula produk, , yang melibatkan langkah Trotter, dan mengindeks jumlah formula produk yang membentuk MPF.
Kuncinya adalah bahwa sisa error Trotter lebih kecil daripada error Trotter yang akan diperoleh jika hanya menggunakan nilai terbesar!
Kamu bisa melihat kegunaan MPF dari dua sudut pandang:
- Untuk anggaran langkah Trotter yang tetap yang bisa kamu eksekusi, kamu bisa mendapatkan hasil dengan error Trotter yang lebih kecil secara total.
- Untuk jumlah langkah Trotter yang menghasilkan Circuit yang dalam, kamu bisa menggunakan MPF untuk menemukan beberapa Circuit dengan kedalaman lebih pendek yang menghasilkan error Trotter serupa.
Pengantar static MPFβ
MPF statis adalah yang nilai -nya TIDAK bergantung pada waktu evolusi, .
Menentukan koefisien MPF statis untuk sekumpulan nilai tertentu setara dengan menyelesaikan sistem persamaan linear: , di mana adalah koefisien yang kita cari, adalah matriks yang bergantung pada dan jenis PF yang kita gunakan (), dan adalah vektor batasan. Untuk singkatnya, kita tidak akan membahas lebih dalam di sini dan sebagai gantinya merujuk kamu ke dokumentasi LSE.
Kita bisa menemukan solusi untuk secara analitik sebagai , lihat misalnya Carrera Vazquez et al., 2023 atau Zhuk et al., 2023. Namun, solusi eksak ini bisa "ill-conditioned" sehingga menghasilkan norma L1 yang sangat besar dari koefisien kita, , yang bisa menyebabkan performa MPF yang buruk. Sebagai alternatif, kita juga bisa mendapatkan solusi aproksimasi yang meminimalkan norma L1 dari untuk mencoba mengoptimalkan perilaku MPF.
Berikut ini, kamu akan belajar cara melakukan semua itu.
Memilih β
Pilihan terserah kepada pengguna. Pada prinsipnya, nilai apa pun bisa dipilih tetapi beberapa akan menyebabkan amplifikasi noise yang lebih besar pada perangkat nyata dibandingkan pilihan lainnya. Oleh karena itu, penting untuk mencoba menemukan nilai yang "baik".
Di sini, kita akan memilih beberapa nilai tetap untuk . Nilai terkecil dimotivasi oleh target waktu evolusi yang biasanya memberitahu kita untuk memenuhi tetapi secara empiris kita tahu bahwa menetapkannya sama dengan biasanya juga berhasil. Jika kamu ingin belajar lebih lanjut tentang ini dan cara memilih nilai lainnya, lihat panduan terkait: How to choose the Trotter steps for an MPF.
time = 8.0
trotter_steps = (8, 12, 19)
Menyiapkan LSEβ
Sekarang setelah kita memilih , kita harus terlebih dahulu membangun LSE, seperti yang dijelaskan di atas.
Matriks tidak hanya bergantung pada tetapi juga pilihan formula produk (PF) kita -- khususnya orde-nya.
Selain itu, kita bisa mempertimbangkan apakah PF simetris atau tidak (lihat Carrera Vazquez et al., 2023), dengan menetapkan symmetric=True.
Namun, ini tidak diperlukan seperti yang ditunjukkan oleh Zhuk et al., 2023.
Di sini, kita akan menggunakan formula Suzuki-Trotter orde kedua yang menghasilkan order=2 dan kita akan menetapkan symmetric=True.
from qiskit_addon_mpf.static import setup_static_lse
lse = setup_static_lse(trotter_steps, order=2, symmetric=True)
print(lse)
LSE(A=array([[1.00000000e+00, 1.00000000e+00, 1.00000000e+00],
[1.56250000e-02, 6.94444444e-03, 2.77008310e-03],
[2.44140625e-04, 4.82253086e-05, 7.67336039e-06]]), b=array([1., 0., 0.]))
Menyelesaikan secara analitikβ
Seperti yang disebutkan sebelumnya, kita bisa menemukan secara analitik:
import numpy as np
coeffs_analytical = lse.solve()
print(coeffs_analytical)
[ 0.17239057 -1.19447005 2.02207947]
Mengoptimalkan menggunakan model eksakβ
Sebagai alternatif dari komputasi , kamu juga bisa menggunakan setup_exact_problem untuk membangun instance cvxpy.Problem yang menggunakan LSE sebagai batasan dan solusi optimalnya akan menghasilkan .
Di bagian berikutnya, akan terlihat mengapa antarmuka ini ada.
from qiskit_addon_mpf.costs import setup_exact_problem
model_exact, coeffs_exact = setup_exact_problem(lse)
model_exact.solve()
print(coeffs_exact.value)
[ 0.17239057 -1.19447005 2.02207947]
Sebagai indikator apakah MPF yang dibangun dengan koefisien ini akan menghasilkan hasil yang baik, kita bisa menggunakan norma L1 (lihat juga Carrera Vazquez et al., 2023).
print(np.linalg.norm(coeffs_exact.value, ord=1))
3.3889400921655914
Mengoptimalkan menggunakan model aproksimasiβ
Bisa terjadi bahwa norma L1 untuk sekumpulan nilai yang dipilih dianggap terlalu tinggi. Jika demikian dan kamu tidak bisa memilih kumpulan nilai yang berbeda, kamu bisa menggunakan solusi aproksimasi untuk LSE sebagai pengganti solusi eksak.
Untuk melakukannya, cukup gunakan setup_sum_of_squares_problem untuk membangun instance cvxpy.Problem yang berbeda yang membatasi norma L1 pada ambang batas tertentu sambil meminimalkan perbedaan antara dan .
from qiskit_addon_mpf.costs import setup_sum_of_squares_problem
model_approx, coeffs_approx = setup_sum_of_squares_problem(lse, max_l1_norm=3.0)
model_approx.solve()
print(coeffs_approx.value)
print(np.linalg.norm(coeffs_approx.value, ord=1))
[-0.40454257 0.57553173 0.8290123 ]
1.8090865903790838
Perlu dicatat bahwa kamu memiliki kebebasan penuh dalam cara menyelesaikan masalah optimasi ini, artinya kamu bisa mengganti solver optimasi, ambang batas konvergensinya, dan sebagainya. Lihat panduan terkait tentang How to use the approximate model.
1c: Menyiapkan Circuit Trotterβ
Pada titik ini, kita telah menemukan koefisien ekspansi kita, , dan yang tersisa adalah membangkitkan Circuit kuantum Trotterized. Sekali lagi, modul qiskit_addon_utils.problem_generators hadir untuk melakukan hal tersebut:
from qiskit.synthesis import SuzukiTrotter
from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit
circuits = []
for k in trotter_steps:
circ = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(order=2, reps=k),
time=time,
)
circuits.append(circ)
circuits[0].draw("mpl", fold=-1)

circuits[1].draw("mpl", fold=-1)

circuits[2].draw("mpl", fold=-1)

Langkah 2: Optimalkan masalahβ
Biasanya, ini adalah langkah dalam pola di mana kamu mengoptimalkan Circuit untuk eksekusi pada hardware. Di sini, karena kita hanya menggunakan simulator tanpa noise, kita cukup mentranspilasi Circuit kita untuk sebuah GenericBackendV2.
from qiskit.providers.fake_provider import GenericBackendV2
from qiskit.transpiler import generate_preset_pass_manager
backend = GenericBackendV2(num_qubits=10)
transpiler = generate_preset_pass_manager(optimization_level=2, backend=backend)
transpiled_circuits = [transpiler.run(circ) for circ in circuits]
Langkah 3: Jalankan eksperimen kuantumβ
Seperti yang dijelaskan di awal, kita akan melewati langkah optimasi 2 karena kita hanya akan menghitung nilai ekspektasi observable target menggunakan simulator bebas noise, yaitu StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()
job = estimator.run([(circ, observable) for circ in transpiled_circuits])
result = job.result()
Langkah 4: Rekonstruksi hasilβ
Pertama, kita ekstrak nilai ekspektasi individual yang diperoleh untuk masing-masing Circuit Trotter:
evs = [res.data.evs for res in result]
print(evs)
[array(0.23799162), array(0.35754312), array(0.38649906)]
Selanjutnya, kita tinggal menggabungkannya dengan koefisien MPF kita untuk mendapatkan total nilai ekspektasi MPF. Di bawah ini, kita melakukannya untuk masing-masing cara berbeda dalam menghitung .
print("Analytical solution:", evs @ coeffs_analytical)
print("Exact model solution:", evs @ coeffs_exact.value)
print("Approx. model solution:", evs @ coeffs_approx.value)
Analytical solution: 0.3954847855980006
Exact model solution: 0.39548478559800204
Approx. model solution: 0.42991214253489807
Terakhir, untuk masalah kecil ini kita bisa menghitung nilai referensi eksak menggunakan scipy.linalg.expm sebagai berikut:
from scipy.linalg import expm
exp_H = expm(-1j * time * hamiltonian.to_matrix())
initial_state = np.zeros(exp_H.shape[0])
initial_state[0] = 1.0
time_evolved_state = exp_H @ initial_state
exact_obs = time_evolved_state.conj() @ observable.to_matrix() @ time_evolved_state
print(exact_obs.real)
0.40060242487899755
Kita bisa dengan jelas melihat bahwa MPF telah mengurangi error Trotter dibandingkan yang diperoleh dengan PF individual terdalam dengan . Namun, kita juga melihat bahwa model aproksimasi tidak sempurna karena ternyata menghasilkan nilai ekspektasi yang lebih buruk dari solusi eksak. Ini menunjukkan pentingnya menggunakan kriteria konvergensi yang ketat pada model aproksimasi seperti yang akan kamu pelajari dalam panduan How to use the approximate model.