התחלה מהירה
המדריך הזה מציג דוגמה מינימלית עובדת של החבילה qiskit-addon-sqd. אנחנו משתמשים באלכסון קוונטי מבוסס דגימות (SQD) כדי לעדן דגימות רועשות שנלקחו ממעגל קוונטי שמקרב את מצב היסוד של המילטוניאן כימי. אנרגיות מצב היסוד מקורבות על ידי אלכסון ההמילטוניאן בתת-מרחבים שנוצרים מהדגימות המעודנות.
לתהליכי עבודה מקצה לקצה עם הסברים נרחבים יותר שרצים על חומרה קוונטית, אפשר לעיין במדריכים:
-
Sample-based quantum diagonalization: תהליך עבודה עם המילטוניאן כימי
-
Sample-based Krylov quantum diagonalization: תהליך עבודה עם מודל סריג פרמיוני
1. הכנת הקלטים ל-SQD
קודם כול, נגדיר את ההמילטוניאן הכימי ואת המעגל הקוונטי שמקרב את מצב היסוד שלו. המערכת שנחקרת בדוגמה הזו היא N₂ בגיאומטריית שיווי משקל בבסיס STO-3G כששני אורביטלי ליבה קפואים. למערכת הזו יש 8 אורביטלים מרחביים ו-10 אלקטרונים, כלומר המעגל הקוונטי מוגדר על 16 qubits, כאשר qubits 0-7 מייצגים אורביטלי ספין-למעלה ו-qubits 8-15 מייצגים אורביטלי ספין-למטה. מכיוון שזו מערכת קליפה סגורה עם 10 אלקטרונים, אנחנו יודעים שלכל דגימה תקפה פיזיקלית צריך להיות משקל המינג 10, כאשר משקל המינג של החצי השמאלי ושל החצי הימני של מחרוזת הביטים הוא 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. יצירת דגימות רועשות
בתהליך עבודה אמיתי היית מתכנן מעגל ansatz, מבצע לו אופטימיזציה לחומרה ודוגם אותו על ה-QPU. כאן אנחנו מדלגים על זה ובמקום זאת דוגמים 10,000 מחרוזות ביטים אקראיות באופן אחיד. הדגימות שלנו לא מכילות שום מידע על מצב היסוד האמיתי, אבל נראה שפרוטוקול SQD עדיין יכול לשחזר את מצב היסוד האמיתי על ידי עידון חוזר של הדגימות, אלכסון, ושימוש באנרגיות בכל איטרציה כדי להנחות את סבב העידון הבא של מחרוזות הביטים. אנחנו יכולים בסופו של דבר לשחזר את מצב היסוד המדויק בדרך הזו מפני שתת-המרחב שמכיל את מצב היסוד קטן מספיק כדי לחשב אותו במדויק. ליתר דיוק, מכיוון שאנחנו יודעים שלכל חצי של כל מחרוזת ביטים (8 ביטים) צריך להיות משקל המינג 5, אנחנו יודעים שגודלו של תת-מרחב הילברט המלא של המערכת הוא .
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. עיבוד לאחר עם SQD
מטרת אלגוריתם SQD היא לעדן דגימות רועשות שנלקחו מ-QPU ובסופו של דבר לאלכסן את ההמילטוניאן בתת-מרחב שנפרש על ידי הדגימות המעודנות האלה. זה נעשה באופן איטרטיבי כך:
-
עידון הדגימות על ידי סינון לאחר הדגימה, כך שנשארות רק אלה שיש להן מספר חלקיקים נכון הן בתת-המערכת של ספין-למעלה והן בתת-המערכת של ספין-למטה
-
אלכסון בתת-מרחבים קטנים שנפרשים על ידי הדגימות המעודנות ואיסוף מידע על תת-המרחבים שמניבים את האנרגיות הטובות ביותר (הנמוכות ביותר).
-
בכל איטרציה:
-
עידון הדגימות הרועשות על ידי היפוך הסתברותי של ביטים בדגימות עם מספר חלקיקים שגוי. ההסתברויות מחושבות באמצעות המידע על תת-המרחב מהאלכסון האחרון.
-
אלכסון בתת-מרחבים קטנים שנפרשים על ידי הדגימות המעודנות
-
איסוף מידע על תת-המרחבים שמניבים את האנרגיות הטובות ביותר (הנמוכות ביותר)
-
מהפלט אפשר לראות שהאלגוריתם מתכנס לאנרגיית מצב היסוד המדויקת אחרי 6 איטרציות, ושהאלכסון מתבצע על פני תת-מרחב הילברט המלא בממד . כמובן, אלכסון על פני התת-מרחב המלא בדרך כלל אינו אפשרי, ולכן מערכות שלמצב היסוד שלהן יש תמך דליל הן אלה שצפויות ליהנות ביותר מטכניקות אלכסון בתת-מרחב כמו SQD.
למידע נוסף על הפונקציה diagonalize_fermionic_hamiltonian, אפשר לבקר ב-תיעוד ה-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