Lewati ke konten utama
Proyek ini masih dalam tahap beta. Menemukan bug? Buat isu GitHub. Punya pertanyaan atau ide? Tanya di Discussions — kami sangat menghargai masukan kamu!
Bagaimana kualitas terjemahan di halaman ini?

Panduan Cepat

Panduan ini menunjukkan contoh minimal yang berjalan dari paket qiskit-addon-sqd. Kita memakai sample-based quantum diagonalization (SQD) untuk memperbaiki sampel berderau yang diambil dari sebuah circuit kuantum yang mendekati ground state dari Hamiltonian kimia. Energi ground state diaproksimasi dengan mendiagonalisasi Hamiltonian di subruang yang dibentuk oleh sampel yang sudah diperbaiki.

Untuk alur kerja end-to-end yang lebih lengkap penjelasannya dan berjalan di hardware kuantum, lihat tutorial berikut:

1. Siapkan input untuk SQD​

Pertama, kita definisikan Hamiltonian kimia dan circuit kuantum yang mendekati ground state-nya. Sistem yang dipelajari dalam contoh ini adalah N₂ pada geometri kesetimbangan dengan basis STO-3G dan dua orbital inti dibekukan. Sistem ini punya 8 orbital spasial dan 10 elektron, artinya circuit kuantum didefinisikan pada 16 qubit, di mana qubit 0-7 mewakili orbital spin-up dan qubit 8-15 mewakili orbital spin-down. Karena ini sistem closed-shell dengan 10 elektron, kita tahu setiap sampel yang valid secara fisik harus punya hamming weight 10, di mana hamming weight untuk bagian kiri dan kanan bitstring masing-masing adalah 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. Hasilkan sampel berderau​

Dalam alur kerja nyata, kamu akan merancang circuit ansatz, mengoptimalkannya untuk hardware, lalu mengambil sampelnya di QPU. Di sini kita lewati itu dan mengambil 10,000 bitstring acak seragam saja. Meski sampel kita tidak mengandung informasi apa pun tentang ground state sebenarnya, kita akan melihat bahwa protokol SQD tetap bisa memulihkan ground state yang benar dengan memperbaiki sampel ini secara iteratif, mendiagonalisasi, dan memakai energi di tiap iterasi untuk menentukan putaran perbaikan bitstring berikutnya. Kita bisa memulihkan ground state yang eksak dengan cara ini karena subruang yang memuat ground state cukup kecil untuk dihitung secara eksak. Secara spesifik, karena kita tahu setiap separuh dari tiap bitstring (8 bit) harus punya hamming weight 5, kita tahu subruang Hilbert penuh dari sistem ini berukuran (85)2=3136\binom{8}{5}^2=3136.

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​

Tujuan algoritma SQD adalah memperbaiki sampel berderau yang diambil dari QPU dan akhirnya mendiagonalisasi Hamiltonian di subruang yang direntang oleh sampel yang sudah diperbaiki itu. Ini dilakukan secara iteratif sebagai berikut:

  • Perbaiki sampel dengan postselection, hanya mengambil yang punya jumlah partikel benar untuk subsistem spin-up maupun spin-down

  • Diagonalisasi di subruang kecil yang direntang oleh sampel yang sudah diperbaiki, lalu kumpulkan informasi tentang subruang yang menghasilkan energi terbaik (terendah).

  • Untuk setiap iterasi:

    • Perbaiki sampel berderau dengan membalik bit secara probabilistik pada sampel yang jumlah partikelnya salah. Probabilitasnya dihitung dari informasi subruang hasil diagonalisasi terbaru.

    • Diagonalisasi di subruang kecil yang direntang oleh sampel yang sudah diperbaiki

    • Kumpulkan informasi tentang subruang yang menghasilkan energi terbaik (terendah)

Dari output terlihat bahwa algoritma konvergen ke energi ground state yang eksak setelah 6 iterasi dan diagonalisasi dilakukan pada seluruh subruang Hilbert berdimensi (85)2=3136\binom{8}{5}^2=3136. Tentu saja, mendiagonalisasi seluruh subruang biasanya tidak layak, sehingga sistem dengan ground state yang punya support jarang (sparse) paling mungkin diuntungkan oleh teknik diagonalisasi subruang seperti SQD.

Untuk informasi lebih lanjut tentang fungsi diagonalize_fermionic_hamiltonian, kunjungi dokumentasi 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