Mengurangkan ralat Trotter bagi dinamik Hamiltonian dengan formula berbilang produk
Dalam notebook ni, korang akan belajar cara guna Formula Berbilang Produk (MPF) untuk mencapai ralat Trotter yang lebih rendah pada observable kita berbanding ralat yang ditanggung oleh Circuit Trotter paling dalam yang sebenarnya akan kita jalankan. Korang akan buat ni dengan melalui langkah-langkah corak Qiskit:
- Langkah 1: Petakan ke masalah kuantum
- Mulakan Hamiltonian masalah kita
- Guna MPF untuk menjana Circuit evolusi masa yang di-Trotterkan
- Langkah 2: Optimumkan masalah
- Di sini kita transpile Circuit kita untuk GenericBackendV2
- Langkah 3: Jalankan eksperimen
- Guna StatevectorEstimator untuk memudahkan dalam notebook ini
- Langkah 4: Bina semula keputusan
- Kira nilai jangkaan MPF
Langkah 1: Petakan ke masalah kuantumβ
1a: Menyediakan Hamiltonian kitaβ
Kita guna model Ising pada garisan 10 tapak:
di mana adalah kekuatan gandingan antara dua tapak dan adalah medan magnet luaran. Pakej qiskit_addon_utils menyediakan fungsi-fungsi boleh guna semula untuk pelbagai tujuan.
Modul qiskit_addon_utils.problem_generators nya menyediakan fungsi untuk menjana Hamiltonian seperti Heisenberg pada graf sambungan yang diberikan. Graf ini boleh jadi sama ada rustworkx.PyGraph atau CouplingMap yang memudahkan penggunaannya dalam aliran kerja berpusat-Qiskit.
Dalam bahagian berikut, kita cipta garisan mudah 10 Qubit menggunakan kaedah 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")
Seterusnya, kita jana SparsePauliOp pada sambungan yang diberikan dengan pemalar yang dikehendaki.
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 jumlah magnetisasi yang boleh kita bina dengan mudah seperti yang ditunjukkan di bawah:
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 Berbilang Produkβ
MPF mengurangkan ralat Trotter bagi dinamik Hamiltonian melalui gabungan berwajaran beberapa pelaksanaan Circuit.
Untuk lebih jelas, kita takrifkan MPF sebagai:
di mana adalah pekali pemberat kita, adalah matriks ketumpatan yang sepadan dengan keadaan tulen yang diperoleh dengan mengevolusi keadaan awal menggunakan formula produk, , melibatkan langkah Trotter, dan mengindeks bilangan formula produk yang membentuk MPF.
Perkara utama di sini ialah ralat Trotter yang tinggal adalah lebih kecil daripada ralat Trotter yang akan diperoleh dengan hanya menggunakan nilai terbesar!
Korang boleh lihat kegunaan MPF dari dua perspektif:
- Untuk bajet langkah Trotter yang tetap yang boleh korang jalankan, korang boleh dapatkan keputusan dengan ralat Trotter yang lebih kecil secara keseluruhan.
- Untuk bilangan langkah Trotter yang menghasilkan Circuit dalam, korang boleh guna MPF untuk mencari beberapa Circuit kedalaman lebih pendek untuk dijalankan yang menghasilkan ralat Trotter yang serupa.
Pengenalan kepada MPF statikβ
MPF Statik adalah yang mana nilai TIDAK bergantung pada masa evolusi, .
Menentukan pekali MPF statik untuk set nilai yang diberikan adalah bersamaan dengan menyelesaikan sistem persamaan linear: , di mana adalah pekali yang kita minati, adalah matriks yang bergantung pada dan jenis PF yang kita guna (), dan adalah vektor kekangan. Untuk ringkas, kita tidak akan masuk lebih detail di sini dan sebaliknya merujuk korang ke dokumentasi LSE.
Kita boleh cari penyelesaian untuk secara analitik sebagai , lihat contohnya Carrera Vazquez et al., 2023 atau Zhuk et al., 2023. Namun, penyelesaian tepat ini boleh jadi "tidak terkondisi" menghasilkan L1-norm yang sangat besar untuk pekali kita, , yang boleh membawa kepada prestasi MPF yang buruk. Sebaliknya, seseorang juga boleh mendapatkan penyelesaian anggaran yang meminimumkan L1-norm of dalam usaha mengoptimumkan tingkah laku MPF.
Dalam bahagian berikut, korang akan belajar cara buat semua ini.
Memilih β
Pilihan adalah bergantung pada pengguna akhir. Pada dasarnya, sebarang nilai boleh dipilih tetapi ada yang akan membawa kepada amplifikasi hingar yang lebih besar pada peranti sebenar berbanding pilihan lain. Oleh itu, adalah penting untuk cuba mencari nilai yang "baik".
Di sini, kita akan pilih nilai tetap untuk . Nilai terkecil didorong oleh masa evolusi sasaran yang biasanya memberitahu kita untuk memenuhi tetapi secara empirikal kita tahu bahawa menetapkannya sama dengan biasanya berfungsi juga. Jika korang ingin tahu lebih lanjut tentang ini dan cara memilih nilai yang lain, rujuk panduan masing-masing: Cara memilih langkah Trotter untuk MPF.
time = 8.0
trotter_steps = (8, 12, 19)
Menyediakan LSEβ
Sekarang yang kita dah pilih , kita mesti terlebih dahulu bina LSE, seperti yang dijelaskan di atas.
Matriks bukan sahaja bergantung pada tetapi juga pilihan formula produk (PF) kita -- khususnya perintahnya.
Selain itu, seseorang boleh mengambil kira sama ada PF adalah simetri 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 guna formula Suzuki-Trotter perintah kedua yang menghasilkan order=2 dan kita akan tetapkan 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 untuk secara analitikβ
Seperti yang disebutkan sebelum ini, kita boleh cari secara analitik:
import numpy as np
coeffs_analytical = lse.solve()
print(coeffs_analytical)
[ 0.17239057 -1.19447005 2.02207947]
Mengoptimumkan untuk menggunakan model tepatβ
Sebagai alternatif kepada mengira , korang juga boleh guna setup_exact_problem untuk membina contoh cvxpy.Problem yang menggunakan LSE sebagai kekangan dan penyelesaian optimalnya akan menghasilkan .
Dalam bahagian seterusnya, akan jelas kenapa antara muka ini wujud.
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 petunjuk sama ada MPF yang dibina dengan pekali ini akan menghasilkan keputusan yang baik, kita boleh guna L1-norm (lihat juga Carrera Vazquez et al., 2023).
print(np.linalg.norm(coeffs_exact.value, ord=1))
3.3889400921655914
Mengoptimumkan untuk menggunakan model anggaranβ
Mungkin berlaku bahawa norma L1 untuk set nilai yang dipilih dianggap terlalu tinggi. Jika itu berlaku dan korang tidak boleh pilih set nilai yang berbeza, korang boleh guna penyelesaian anggaran untuk LSE sebagai ganti penyelesaian tepat.
Untuk buat begitu, cuma guna setup_sum_of_squares_problem untuk membina contoh cvxpy.Problem yang berbeza yang mengehadkan L1-norm kepada ambang yang dipilih sambil meminimumkan perbezaan 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
Perhatikan, korang ada kebebasan penuh tentang cara menyelesaikan masalah pengoptimuman ini, bermakna korang boleh tukar penyelesai pengoptimuman, ambang penumpuannya, dan sebagainya. Tengok panduan masing-masing tentang Cara guna model anggaran.
1c: Menyediakan Circuit Trotterβ
Pada ketika ini, kita dah jumpa pekali pengembangan kita, , dan yang tinggal ialah menjana Circuit kuantum yang di-Trotterkan. Sekali lagi, modul qiskit_addon_utils.problem_generators datang menyelamatkan untuk buat benda tu:
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: Optimumkan masalahβ
Biasanya, ini adalah langkah dalam corak di mana korang mengoptimumkan Circuit untuk pelaksanaan pada perkakasan. Di sini, oleh sebab kita hanya guna simulator tanpa hingar, kita cuma transpile Circuit kita untuk 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 pada awal tadi, kita akan langkau langkah pengoptimuman 2 kerana kita cuma akan mengira nilai jangkaan observable sasaran kita menggunakan simulator bebas-hingar, iaitu StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()
job = estimator.run([(circ, observable) for circ in transpiled_circuits])
result = job.result()
Langkah 4: Bina semula keputusanβ
Pertama, kita ekstrak nilai jangkaan individu yang diperoleh untuk setiap Circuit Trotter:
evs = [res.data.evs for res in result]
print(evs)
[array(0.23799162), array(0.35754312), array(0.38649906)]
Seterusnya, kita gabungkan semula nilai-nilai itu dengan pekali MPF kita untuk menghasilkan nilai jangkaan keseluruhan MPF. Di bawah, kita buat begitu untuk setiap cara berbeza yang kita gunakan untuk mengira .
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
Akhirnya, untuk masalah kecil ini kita boleh kira nilai rujukan tepat menggunakan scipy.linalg.expm seperti 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 boleh nampak dengan jelas bahawa MPF telah mengurangkan ralat Trotter berbanding yang diperoleh dengan PF individu paling dalam dengan . Namun, kita juga nampak bahawa model anggaran tidak sempurna kerana ia sebenarnya menghasilkan nilai jangkaan yang lebih buruk daripada penyelesaian tepat. Ini menunjukkan kepentingan menggunakan kriteria penumpuan yang ketat pada model anggaran seperti yang akan korang pelajari dalam panduan Cara guna model anggaran.