Permulaan Pantas
Panduan ini menunjukkan contoh minimum yang berfungsi bagi pakej qiskit-addon-sqd. Kami menggunakan pepenyahpepenjuruan kuantum berasaskan sampel (SQD) untuk memperhalus sampel bising yang diambil daripada litar kuantum yang menghampiri keadaan asas Hamiltonian kimia. Tenaga keadaan asas dianggarkan dengan menyahpepenjuruankan Hamiltonian dalam subruang yang dibentuk oleh sampel yang telah diperhalus.
Untuk aliran kerja hujung-ke-hujung yang lebih terperinci dan dijalankan pada perkakasan kuantum, lihat tutorial berikut:
-
Pepenyahpepenjuruan kuantum berasaskan sampel: aliran kerja Hamiltonian kimia
-
Pepenyahpepenjuruan kuantum Krylov berasaskan sampel: aliran kerja model kekisi fermionik
1. Sediakan input untuk SQD
Pertama, kami mentakrifkan Hamiltonian kimia dan litar kuantum yang menghampiri keadaan asasnya. Sistem yang dikaji dalam contoh ini ialah N₂ pada geometri keseimbangan dalam asas STO-3G dengan dua orbital teras dibekukan. Sistem ini mempunyai 8 orbital ruang dan 10 elektron, yang bermakna litar kuantum ditakrifkan pada 16 qubit, dengan qubit 0-7 mewakili orbital spin-atas dan qubit 8-15 mewakili orbital spin-bawah. Oleh sebab ini ialah sistem lapisan tertutup dengan 10 elektron, kita tahu setiap sampel yang sah secara fizikal harus mempunyai berat hamming 10, dengan berat hamming bagi separuh kiri dan separuh kanan rentetan bit masing-masing ialah 5.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"numpy": "numpy", "pyscf": "pyscf", "qiskit_addon_sqd": "qiskit-addon-sqd"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from pyscf import ao2mo, gto, mcscf, scf
# Construct the Hamiltonian, pull out integrals and other information about the system
mol = gto.M(
atom="N 0 0 0; N 0 0 1.09768", basis="sto-3g", spin=0, charge=0, verbose=0
)
mf = scf.RHF(mol).run()
cas = mcscf.CASCI(mf, ncas=8, nelecas=10)
hcore, nuclear_repulsion_energy = cas.get_h1eff()
eri = cas.get_h2eff()
num_orbitals = cas.ncas
eri = ao2mo.restore(1, eri, num_orbitals)
n_alpha, n_beta = cas.nelecas
nelec = (n_alpha, n_beta)
print(
f"Spatial orbitals: {num_orbitals}\nQubits: {num_orbitals * 2}\nElectrons (alpha, beta): {nelec}"
)
Spatial orbitals: 8
Qubits: 16
Electrons (alpha, beta): (5, 5)
2. Jana sampel bising
Dalam aliran kerja sebenar, anda akan mereka bentuk litar ansatz, mengoptimumkannya untuk perkakasan, dan mensampelnya pada QPU. Di sini kami melangkaunya dan sebaliknya melukis 10,000 rentetan bit rawak seragam. Walaupun sampel kami tidak mengandungi maklumat tentang keadaan asas sebenar, kita akan melihat bahawa protokol SQD masih boleh memulihkan keadaan asas sebenar dengan memperhalus sampel ini secara berulang, menyahpepenjuruankan, dan menggunakan tenaga pada setiap lelaran untuk memaklumkan pusingan penghalusan rentetan bit seterusnya. Kita akhirnya dapat memulihkan keadaan asas yang tepat dengan cara ini kerana subruang yang mengandungi keadaan asas cukup kecil untuk dikira dengan tepat. Khususnya, memandangkan kita tahu setiap separuh bagi setiap rentetan bit (8 bit) harus mempunyai berat hamming 5, kita tahu subruang Hilbert penuh bagi sistem ini bersaiz .
import numpy as np
from qiskit_addon_sqd.counts import generate_bit_array_uniform
# Generate some uniformly-random bitstrings to simulate QPU samples
rng = np.random.default_rng(24)
bit_array = generate_bit_array_uniform(
10_000, num_orbitals * 2, rand_seed=rng
)
print(
f"Generated {bit_array.num_shots} uniformly-random, {bit_array.num_bits}-qubit samples."
)
Generated 10000 uniformly-random, 16-qubit samples.
3. Pasca-proses dengan SQD
Objektif algoritma SQD ialah memperhalus sampel bising yang diambil daripada QPU dan akhirnya menyahpepenjuruankan Hamiltonian dalam subruang yang direntangi oleh sampel yang telah diperhalus itu. Ini dilakukan secara berulang seperti berikut:
-
Perhalus sampel dengan pascapemilihan hanya sampel yang mempunyai bilangan zarah yang betul bagi kedua-dua subsistem spin-atas dan spin-bawah
-
Nyahpepenjuruankan dalam subruang kecil yang direntangi oleh sampel yang telah diperhalus dan kumpulkan maklumat tentang subruang yang menghasilkan tenaga terbaik (terendah).
-
Untuk setiap lelaran:
-
Perhalus sampel bising dengan membalikkan bit secara berkebarangkalian dalam sampel yang mempunyai bilangan zarah yang salah. Kebarangkalian dikira menggunakan maklumat subruang daripada penyahpepenjuruanan terkini.
-
Nyahpepenjuruankan dalam subruang kecil yang direntangi oleh sampel yang telah diperhalus
-
Kumpulkan maklumat tentang subruang yang menghasilkan tenaga terbaik (terendah)
-
Kita dapat melihat daripada output bahawa algoritma menumpu kepada tenaga keadaan asas yang tepat selepas 6 lelaran dan bahawa penyahpepenjuruanan dilakukan ke atas subruang Hilbert penuh berdimensi . Sudah tentu, penyahpepenjuruanan ke atas subruang penuh biasanya tidak boleh dilaksanakan, dan oleh itu, sistem dengan keadaan asas yang mempunyai sokongan jarang paling berkemungkinan mendapat manfaat daripada teknik penyahpepenjuruanan subruang seperti SQD.
Untuk maklumat lanjut tentang fungsi diagonalize_fermionic_hamiltonian, lawati dokumen API.
from functools import partial
from pyscf import fci
from qiskit_addon_sqd.fermion import (
SCIResult,
diagonalize_fermionic_hamiltonian,
solve_sci_batch,
)
exact_energy, _ = fci.direct_spin1.kernel(
hcore, eri, int(num_orbitals), nelec
)
exact_energy += nuclear_repulsion_energy
print(f"Exact (FCI) reference energy: {exact_energy:.6f} Ha\n")
sci_solver = partial(solve_sci_batch, spin_sq=0.0, max_cycle=200)
result_history = []
def callback(results: list[SCIResult]):
result_history.append(results)
iteration = len(result_history)
print(f"Iteration {iteration}")
for i, result in enumerate(results):
error = result.energy + nuclear_repulsion_energy - exact_energy
print(f" Subsample {i}")
print(f" Energy: {result.energy + nuclear_repulsion_energy:.6f}")
print(
f" Subspace dimension: {np.prod(result.sci_state.amplitudes.shape)}"
)
print(f" Error vs exact: {error:.6f} Ha")
samples_per_batch = 20
result = diagonalize_fermionic_hamiltonian(
hcore,
eri,
bit_array,
samples_per_batch=samples_per_batch,
norb=num_orbitals,
nelec=nelec,
occupancies_tol=1e-7,
max_iterations=30,
sci_solver=sci_solver,
symmetrize_spin=True,
callback=callback,
seed=np.random.default_rng(32),
)
Exact (FCI) reference energy: -107.652521 Ha
Iteration 1
Subsample 0
Energy: -106.908481
Subspace dimension: 784
Error vs exact: 0.744040 Ha
Iteration 2
Subsample 0
Energy: -106.934921
Subspace dimension: 1764
Error vs exact: 0.717600 Ha
Iteration 3
Subsample 0
Energy: -106.953430
Subspace dimension: 2209
Error vs exact: 0.699091 Ha
Iteration 4
Subsample 0
Energy: -107.651946
Subspace dimension: 2916
Error vs exact: 0.000575 Ha
Iteration 5
Subsample 0
Energy: -107.652003
Subspace dimension: 3025
Error vs exact: 0.000518 Ha
Iteration 6
Subsample 0
Energy: -107.652521
Subspace dimension: 3136
Error vs exact: 0.000000 Ha
Iteration 7
Subsample 0
Energy: -107.652521
Subspace dimension: 3136
Error vs exact: 0.000000 Ha