דלג לתוכן הראשי

המילטוניאנים לכימיה קוונטית

נתחיל בסקירה קצרה של תפקיד ההמילטוניאנים ב-VQE.

סקירה של ההמילטוניאן ב-VQE

ד"ר ויקטוריה ליפינסקה מדריכה אותנו בנושא המילטוניאנים וכיצד למפות אותם לשימוש בחישוב קוונטי.

מקורות

המאמרים הבאים מוזכרים בסרטון שלמעלה.

הכנת המילטוניאנים לכימיה קוונטית

צעד ראשון טוב ביישום חישוב קוונטי לבעיה כימית הוא הגדרת המילטוניאן עבור המערכת שמעניינת אותנו. כאן נגביל את הדיון להמילטוניאנים של כימיה קוונטית, שכן אותם המילטוניאנים דורשים מיפוי מיוחד למערכות של פרמיונים זהים.

כמי שעובד בכימיה קוונטית, כנראה כבר יש לך תוכנת המודלינג המועדפת עליך למולקולות, שיכולה לייצר המילטוניאן המתאר את המערכת שמעניינת אותך. כאן נשתמש בקוד שנבנה אך ורק על PySCF, numpy, ו-Qiskit. אך תהליך הכנת ההמילטוניאן עובר גם לפתרונות ארוזים מראש. ההבדל היחיד בין גישה זו לתוכנות אחרות יהיה הבדלי תחביר קלים; חלק מאלה מטופלים בסעיף "תוכנות צד שלישי" כדי להקל על שילוב תהליכי עבודה קיימים.

יצירת המילטוניאן לכימיה קוונטית לשימוש ב-IBM Quantum® QPUs כוללת את השלבים הבאים:

  1. הגדר את המולקולה שלך (גיאומטריה, ספין, מרחב פעיל, וכן הלאה)
  2. צור את ההמילטוניאן הפרמיוני (אופרטורי יצירה ואפסה)
  3. מפה מהמילטוניאן הפרמיוני לאופרטור בוזוני (בהקשר זה, תוך שימוש באופרטורי פאולי)
  4. אם משתמשים בתוכנת צד שלישי: טפל בחוסר-התאמות תחביריות בין תוכנת הייצור ל-Qiskit

ההמילטוניאן הפרמיוני כתוב במונחים של אופרטורים פרמיוניים, ובפרט לוקח בחשבון שאלקטרונים הם פרמיונים בלתי-ניתנים להבחנה. פירוש הדבר שהם מציתים סטטיסטיקה שונה לחלוטין מ-Qubitים בוזוניים הניתנים להבחנה. מכאן תהליך המיפוי.

מי שכבר מכיר את התהליכים האלה יכול כנראה לדלג על סעיף זה. מטרה:

המטרה הסופית היא להשיג המילטוניאן בצורה הבאה:

# Added by doQumentation — required packages for this notebook
!pip install -q numpy openfermion pyscf qiskit
H = [(1, "XX"), (1, "YY"), (1, "ZZ")]
print(H)
[(1, 'XX'), (1, 'YY'), (1, 'ZZ')]

או

from qiskit.quantum_info import SparsePauliOp

H = SparsePauliOp(["XX", "YY", "ZZ"], coeffs=[1.0 + 0.0j, 1.0 + 0.0j, 1.0 + 0.0j])
print(H)
SparsePauliOp(['XX', 'YY', 'ZZ'],
coeffs=[1.+0.j, 1.+0.j, 1.+0.j])

נתחיל בייבוא כמה חבילות:

import numpy as np
from pyscf import ao2mo, gto, mcscf, scf
  1. הגדר את המולקולה שלך

כאן נציין תכונות של המולקולה שמעניינת אותנו. בדוגמה זו בחרנו במימן דיאטומי (מכיוון שההמילטוניאנים המתקבלים קצרים מספיק להצגה). ה-Python-based Simulations of Chemistry Framework (PySCF) כולל אוסף רחב של מודולי מבנה אלקטרוני שניתן להשתמש בהם, בין היתר, לייצור המילטוניאנים מולקולריים המתאימים לחישוב קוונטי. מדריך PySCF Quickstart הוא משאב מצוין לתיאור מלא של כל המשתנים והפונקציונליות. נתן רק סקירה שטחית ביותר, שכן זה כבר יהיה מוכר לרבים מכם. כדי להבין אותם טוב יותר, בקר ב-PySCF. בקצרה:

distance יכול לשמש למולקולות דיאטומיות, או פשוט לציין קואורדינטות קרטזיות לכל אטום. המרחקים הם ביחידות אנגסטרום.

gto מייצר אורביטלים מסוג גאוסיאן.

basis מתייחס לפונקציות המשמשות לדגמון אורביטלים מולקולריים. כאן 'sto-6g' הוא בסיס מינימלי נפוץ, שנקרא כך בגלל התאמת Slater-Type Orbitals תוך שימוש ב-6 אורביטלים גאוסיאניים פרימיטיביים.

spin ערך שלם המציין את מספר האלקטרונים הבלתי-מותאמים (שווה ל-2S2S). שים לב שחלק מהתוכנות משתמשות במולטיפליציטי במקום (2S+12S+1).

charge המטען של המולקולה.

symmetry - קבוצת הסימטריה הנקודתית של המולקולה, הנקבעת עם מחרוזת או מזוהה אוטומטית על ידי הגדרת "symmetry = True". כאן "Dooh" היא קבוצת הסימטריה המתאימה למולקולות דיאטומיות עם שני אטומים מאותו מין.

distance = 0.735
a = distance / 2
mol = gto.Mole()
mol.build(
verbose=0,
atom=[
["H", (0, 0, -a)],
["H", (0, 0, a)],
],
basis="sto-6g",
spin=0,
charge=0,
symmetry="Dooh",
)
<pyscf.gto.mole.Mole at 0x7fc718f07610>

זכור שניתן לתאר אנרגיה כוללת (הכוללת אנרגיית דחיית גרעינים וכן אלקטרונית), אנרגיית אורביטל אלקטרוני כולל, או את האנרגיה של תת-קבוצה כלשהי של אורביטלים אלקטרוניים (כאשר התת-קבוצה המשלימה קפואה). במקרה הספציפי של H2\text{H}_2, שים לב לאנרגיות השונות להלן, ושים לב שהאנרגיה הכוללת פחות אנרגיית דחיית הגרעינים מניבה אכן את האנרגיה האלקטרונית:

mf = scf.RHF(mol)
mf.scf()

print(
mf.energy_nuc(),
mf.energy_elec()[0],
mf.energy_tot(),
mf.energy_tot() - mol.energy_nuc(),
)
0.7199689944489797 -1.8455976628764188 -1.125628668427439 -1.8455976628764188
active_space = range(mol.nelectron // 2 - 1, mol.nelectron // 2 + 1)
  1. צור המילטוניאן פרמיוני

scf מתייחס למגוון רחב של שיטות שדה עצמי-עקבי.

rhf כפי שב-mf = scf.RHF(mol) ב-mf הוא פותר המשתמש בחישוב Restricted Hartree Fock. הגרעין שלו (E, להלן) הוא האנרגיה הכוללת, כולל דחיית גרעינים ואורביטלים מולקולריים.

mcscf הוא חבילת שדות עצמי-עקביים רב-תצורה.

ao2mo הוא טרנספורמציה מאורביטלים אטומיים לאורביטלים מולקולריים.

אנחנו גם משתמשים במשתנים הבאים:

ncas: מספר האורביטלים במרחב הפעיל המלא

nelecas: מספר האלקטרונים במרחב הפעיל המלא

E1 = mf.kernel()
mx = mcscf.CASCI(mf, ncas=2, nelecas=(1, 1))
mo = mx.sort_mo(active_space, base=0)
E2 = mx.kernel(mo)[:2]

אנחנו רוצים המילטוניאן, וזה לעיתים קרובות מחולק לאנרגיה של ליבה אלקטרונית (ecore, לא מעורב במינימיזציה), אופרטורים חד-אלקטרוניים (h1e), ואנרגיות דו-אלקטרוניות (h2e). אלה מחולצים במפורש להלן בשתי השורות האחרונות.

h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)

ההמילטוניאנים האלה הם כרגע אופרטורים פרמיוניים (יצירה ואפסה), הרלוונטיים למערכות של פרמיונים (בלתי-ניתנים להבחנה), ובהתאם כפופים לאנטי-סימטריה תחת החלפה. זה מביא לסטטיסטיקה שונה מזו שתחול על מערכת ניתנת להבחנה או בוזונית. כדי להפעיל חישובים על IBM Quantum QPUs, אנחנו זקוקים לאופרטור בוזוני המתאר את האנרגיה. תוצאת מיפוי כזה כתובה באופן מקובל במונחים של אופרטורי פאולי, מכיוון שהם גם הרמיטיים וגם אוניטריים. ישנם מספר מיפויים שניתן להשתמש בהם. אחד הפשוטים הוא טרנספורמציית Jordan Wigner.

  1. מיפוי ההמילטוניאן

ראוי לציין שיש כלים רבים הזמינים למיפוי המילטוניאן כימי לאחד המתאים להפעלה על מחשב קוונטי. כאן אנחנו מממשים את מיפוי Jordan Wigner ישירות תוך שימוש רק ב-PySCF, numpy, ו-Qiskit. אנחנו מגיבים להלן על שיקולי תחביר לפתרונות אחרים. פונקציית Cholesky עוזרת לנו לקבל פירוק דרגה-נמוכה של המונחים הדו-אלקטרוניים בהמילטוניאן.

def cholesky(V, eps):
# see https://arxiv.org/pdf/1711.02242.pdf section B2
# see https://arxiv.org/abs/1808.02625
# see https://arxiv.org/abs/2104.08957
no = V.shape[0]
chmax, ng = 20 * no, 0
W = V.reshape(no**2, no**2)
L = np.zeros((no**2, chmax))
Dmax = np.diagonal(W).copy()
nu_max = np.argmax(Dmax)
vmax = Dmax[nu_max]
while vmax > eps:
L[:, ng] = W[:, nu_max]
if ng > 0:
L[:, ng] -= np.dot(L[:, 0:ng], (L.T)[0:ng, nu_max])
L[:, ng] /= np.sqrt(vmax)
Dmax[: no**2] -= L[: no**2, ng] ** 2
ng += 1
nu_max = np.argmax(Dmax)
vmax = Dmax[nu_max]
L = L[:, :ng].reshape((no, no, ng))
print(
"accuracy of Cholesky decomposition ",
np.abs(np.einsum("prg,qsg->prqs", L, L) - V).max(),
)
return L, ng

הפונקציות identity ו-creators_destructors מחליפות אופרטורי יצירה ואפסה בהמילטוניאן הפרמיוני באופרטורי פאולי; creators_destructors משתמשת במיפוי Jordan-Wigner.

def identity(n):
return SparsePauliOp.from_list([("I" * n, 1)])

def creators_destructors(n, mapping="jordan_wigner"):
c_list = []
if mapping == "jordan_wigner":
for p in range(n):
if p == 0:
ell, r = "I" * (n - 1), ""
elif p == n - 1:
ell, r = "", "Z" * (n - 1)
else:
ell, r = "I" * (n - p - 1), "Z" * p
cp = SparsePauliOp.from_list([(ell + "X" + r, 0.5), (ell + "Y" + r, -0.5j)])
c_list.append(cp)
else:
raise ValueError("Unsupported mapping.")
d_list = [cp.adjoint() for cp in c_list]
return c_list, d_list

לבסוף, build_hamiltonian משתמשת בפונקציות cholesky, identity, ו-creators_destructors כדי ליצור את ההמילטוניאן הסופי המתאים להפעלה על מחשב קוונטי.

def build_hamiltonian(ecore: float, h1e: np.ndarray, h2e: np.ndarray) -> SparsePauliOp:
ncas, _ = h1e.shape

C, D = creators_destructors(2 * ncas, mapping="jordan_wigner")
Exc = []
for p in range(ncas):
Excp = [C[p] @ D[p] + C[ncas + p] @ D[ncas + p]]
for r in range(p + 1, ncas):
Excp.append(
C[p] @ D[r]
+ C[ncas + p] @ D[ncas + r]
+ C[r] @ D[p]
+ C[ncas + r] @ D[ncas + p]
)
Exc.append(Excp)

# low-rank decomposition of the Hamiltonian
Lop, ng = cholesky(h2e, 1e-6)
t1e = h1e - 0.5 * np.einsum("pxxr->pr", h2e)

H = ecore * identity(2 * ncas)
# one-body term
for p in range(ncas):
for r in range(p, ncas):
H += t1e[p, r] * Exc[p][r - p]
# two-body term
for g in range(ng):
Lg = 0 * identity(2 * ncas)
for p in range(ncas):
for r in range(p, ncas):
Lg += Lop[p, r, g] * Exc[p][r - p]
H += 0.5 * Lg @ Lg

return H.chop().simplify()

לבסוף, אנחנו משתמשים ב-build_hamiltonian כדי לבנות את המילטוניאן ה-Qubit שלנו מאופרטורי פאולי תוך שימוש בטרנספורמציית Jordan-Wigner. זה גם נותן לנו את הדיוק של פירוק Cholesky שהשתמשנו בו.

H = build_hamiltonian(ecore, h1e, h2e)
print(H)
accuracy of Cholesky decomposition  2.220446049250313e-16
SparsePauliOp(['IIII', 'IIIZ', 'IZII', 'IIZI', 'ZIII', 'IZIZ', 'IIZZ', 'ZIIZ', 'IZZI', 'ZZII', 'ZIZI', 'YYYY', 'XXYY', 'YYXX', 'XXXX'],
coeffs=[-0.09820182+0.j, -0.1740751 +0.j, -0.1740751 +0.j, 0.2242933 +0.j,
0.2242933 +0.j, 0.16891402+0.j, 0.1210099 +0.j, 0.16631441+0.j,
0.16631441+0.j, 0.1210099 +0.j, 0.17504456+0.j, 0.04530451+0.j,
0.04530451+0.j, 0.04530451+0.j, 0.04530451+0.j])

מחברת מולקולה לדוגמה זו מציגה את ההגדרה וההמילטוניאנים עבור מספר מולקולות בסיבוכיות משתנה; עם שינוי קל, זה אמור לאפשר לך לבחון את רוב המולקולות הקטנות.

בואו פשוט נציין בקצרה שתי נקודות חשובות שיש לקחת בחשבון בבניית האופרטורים הפרמיוניים עבור מולקולה. כשסוג המולקולה משתנה, הסימטריה תשתנה. באופן דומה, מספר האורביטלים עם סימטריות שונות, כמו "A1" הסימטרי גלילי, ישתנה. שינויים אלה ניכרים אפילו עם ההרחבה הפשוטה ל-LiH, כפי שניתן לראות כאן:

distance = 1.56
mol = gto.Mole()
mol.build(
verbose=0,
atom=[["Li", (0, 0, 0)], ["H", (0, 0, distance)]],
basis="sto-6g",
spin=0,
charge=0,
symmetry="Coov",
)
mf = scf.RHF(mol)
E1 = mf.kernel()

# %% ----------------------------------------------------------------------------------------------

mx = mcscf.CASCI(mf, ncas=5, nelecas=(1, 1))
cas_space_symmetry = {"A1": 3, "E1x": 1, "E1y": 1}
mo = mcscf.sort_mo_by_irrep(mx, mf.mo_coeff, cas_space_symmetry)
E2 = mx.kernel(mo)[:2]
h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)

ראוי גם לציין שניתן לאבד במהירות את האינטואיציה להמילטוניאן הסופי המתקבל. ההמילטוניאן של LiH (תוך שימוש במפה Jordan-Wigner) כבר מורכב מ-276 מונחים.

len(build_hamiltonian(ecore, h1e, h2e))
accuracy of Cholesky decomposition  1.1102230246251565e-16
276

כשיש ספק לגבי סימטריות, ניתן גם לייצר מידע סימטריה עבור המולקולה על ידי הגדרת symmetry = True ו-verbose = 4:

distance = 1.56
mol = gto.Mole()
mol.build(
verbose=4,
atom=[["Li", (0, 0, 0)], ["H", (0, 0, distance)]],
basis="sto-6g",
spin=0,
charge=0,
symmetry=True,
)
System: uname_result(system='Linux', node='IBM-R912JTRT', release='5.10.102.1-microsoft-standard-WSL2', version='#1 SMP Wed Mar 2 00:30:59 UTC 2022', machine='x86_64')  Threads 16
Python 3.11.12 (main, May 16 2025, 02:33:32) [GCC 11.4.0]
numpy 2.3.1 scipy 1.16.0 h5py 3.14.0
Date: Mon Jun 30 12:56:55 2025
PySCF version 2.9.0
PySCF path /home/porter284/.pyenv/versions/3.11.12/lib/python3.11/site-packages/pyscf

[CONFIG] conf_file None
[INPUT] verbose = 4
[INPUT] num. atoms = 2
[INPUT] num. electrons = 4
[INPUT] charge = 0
[INPUT] spin (= nelec alpha-beta = 2S) = 0
[INPUT] symmetry True subgroup None
[INPUT] Mole.unit = angstrom
[INPUT] Symbol X Y Z unit X Y Z unit Magmom
[INPUT] 1 Li 0.000000000000 0.000000000000 0.000000000000 AA 0.000000000000 0.000000000000 0.000000000000 Bohr 0.0
[INPUT] 2 H 0.000000000000 0.000000000000 1.560000000000 AA 0.000000000000 0.000000000000 2.947972754321 Bohr 0.0

nuclear repulsion = 1.01764848253846
point group symmetry = Coov
symmetry origin: [0. 0. 0.73699319]
symmetry axis x: [1. 0. 0.]
symmetry axis y: [0. 1. 0.]
symmetry axis z: [0. 0. 1.]
num. orbitals of irrep A1 = 4
num. orbitals of irrep E1x = 1
num. orbitals of irrep E1y = 1
number of shells = 4
number of NR pGTOs = 36
number of NR cGTOs = 6
basis = sto-6g
ecp = {}
CPU time: 9.85
<pyscf.gto.mole.Mole at 0x7fc719f94850>

בין שאר המידע השימושי, זה מחזיר גם את point group symmetry = Coov וגם את מספר האורביטלים בכל ייצוג בלתי-ניתן לצמצום.

point group symmetry = Coov
num. orbitals of irrep A1 = 4
num. orbitals of irrep E1x = 1
num. orbitals of irrep E1y = 1
number of shells = 4

זה לא בהכרח אומר לך כמה אורביטלים אתה רוצה לכלול במרחב הפעיל שלך, אבל זה עוזר לך לראות אילו אורביטלים קיימים וסימטריותיהם.

ציון סימטריה ואורביטלים לעיתים קרובות מועיל, אבל אתה יכול גם לציין את מספר האורביטלים שאתה רוצה לכלול. שקול את המקרה של אתן, להלן. תוך שימוש ב-verbose = 4, ניתן להדפיס את הסימטריות של האורביטלים השונים:

# Replace these variables with correct distances:
a = 1
b = 1
c = 1

# Build
mol = gto.Mole()
mol.build(
verbose=4,
atom=[
["C", (0, 0, a)],
["C", (0, 0, -a)],
["H", (0, c, b)],
["H", (0, -c, b)],
["H", (0, c, -b)],
["H", (0, -c, -b)],
],
basis="sto-6g",
spin=0,
charge=0,
symmetry=True,
)
System: uname_result(system='Linux', node='IBM-R912JTRT', release='5.10.102.1-microsoft-standard-WSL2', version='#1 SMP Wed Mar 2 00:30:59 UTC 2022', machine='x86_64')  Threads 16
Python 3.11.12 (main, May 16 2025, 02:33:32) [GCC 11.4.0]
numpy 2.3.1 scipy 1.16.0 h5py 3.14.0
Date: Mon Jun 30 12:57:07 2025
PySCF version 2.9.0
PySCF path /home/porter284/.pyenv/versions/3.11.12/lib/python3.11/site-packages/pyscf

[CONFIG] conf_file None
[INPUT] verbose = 4
[INPUT] num. atoms = 6
[INPUT] num. electrons = 16
[INPUT] charge = 0
[INPUT] spin (= nelec alpha-beta = 2S) = 0
[INPUT] symmetry True subgroup None
[INPUT] Mole.unit = angstrom
[INPUT] Symbol X Y Z unit X Y Z unit Magmom
[INPUT] 1 C 0.000000000000 0.000000000000 1.000000000000 AA 0.000000000000 0.000000000000 1.889726124565 Bohr 0.0
[INPUT] 2 C 0.000000000000 0.000000000000 -1.000000000000 AA 0.000000000000 0.000000000000 -1.889726124565 Bohr 0.0
[INPUT] 3 H 0.000000000000 1.000000000000 1.000000000000 AA 0.000000000000 1.889726124565 1.889726124565 Bohr 0.0
[INPUT] 4 H 0.000000000000 -1.000000000000 1.000000000000 AA 0.000000000000 -1.889726124565 1.889726124565 Bohr 0.0
[INPUT] 5 H 0.000000000000 1.000000000000 -1.000000000000 AA 0.000000000000 1.889726124565 -1.889726124565 Bohr 0.0
[INPUT] 6 H 0.000000000000 -1.000000000000 -1.000000000000 AA 0.000000000000 -1.889726124565 -1.889726124565 Bohr 0.0

nuclear repulsion = 29.3377079104231
point group symmetry = D2h
symmetry origin: [0. 0. 0.]
symmetry axis x: [0. 1. 0.]
symmetry axis y: [1. 0. 0.]
symmetry axis z: [-0. -0. -1.]
num. orbitals of irrep Ag = 4
num. orbitals of irrep B2g = 2
num. orbitals of irrep B3g = 1
num. orbitals of irrep B1u = 4
num. orbitals of irrep B2u = 1
num. orbitals of irrep B3u = 2
number of shells = 10
number of NR pGTOs = 84
number of NR cGTOs = 14
basis = sto-6g
ecp = {}
CPU time: 9.92
<pyscf.gto.mole.Mole at 0x7fc719fa9290>

אנחנו מקבלים:

num. orbitals of irrep Ag = 4

num. orbitals of irrep B2g = 2

num. orbitals of irrep B3g = 1

num. orbitals of irrep B1u = 4

num. orbitals of irrep B2u = 1

num. orbitals of irrep B3u = 2

אבל במקום לציין את כל האורביטלים לפי סימטריה, ניתן פשוט לכתוב:

active_space = range(mol.nelectron // 2 - 2, mol.nelectron // 2 + 2)

בגישה זו אנחנו לוקחים מספר אורביטלים ליד רמת המילוי (ערכיות ולא-תפוסים). כאן נבחרו 5 אורביטלים לצורך הכללה במרחב הפעיל (ה-6 עד ה-10).

print(
mol.nelectron // 2 - 2,
mol.nelectron // 2 + 2,
)
6 10
  1. תוכנות צד שלישי

ישנן מספר חבילות תוכנה שפותחו לכימיה קוונטית, כשחלקן מציעות מפות מרובות וכלים להגבלת מרחבים פעילים. הצעדים המתוארים לעיל הם כלליים וחלים גם על תוכנות צד שלישי. אך תוכנות אחרות אלה עשויות להחזיר המילטוניאנים בפורמט שאינו מקובל על ידי Qiskit. לדוגמה, חלק מהתוכנות מחזירות המילטוניאנים בצורה הבאה:

H = -0.042 [] + -0.045 [X0 X1 Y2 Y3] + ... + 0.178 [Z0] + ... + 0.176 [Z2 Z3] + -0.243 [Z3] שים לב במיוחד שה-Gate-ים ממוספרים, ואופרטורי הזהות אינם מוצגים. זה בניגוד להמילטוניאנים המשמשים ב-Qiskit, שיכתבו את המונח [Z2 Z3] כ-ZZII (Qubitים 0 ו-1 פועלים על ידי אופרטור הזהות, Qubitים 2 ו-3 פועלים על ידי אופרטור Z, מסודרים כאשר Qubit 0 נמצא הרחק ביותר מימין).

כדי להתאים לכל תהליכי עבודה קיימים שיש לך, בלוק הקוד שלהלן ממיר מתחביר אחד לאחר. הפונקציה convert_openfermion_to_qiskit מקבלת כארגומנטים המילטוניאן שנוצר ב-OpenFermion או Tangelo (וכבר ממופה על אופרטורי פאולי תוך שימוש בכל מפה זמינה), ומספר ה-Qubitים הדרושים למולקולה.

from openfermion import QubitOperator
from qiskit.quantum_info import SparsePauliOp

def convert_openfermion_to_qiskit(
openfermion_operator: QubitOperator, num_qubits: int
) -> SparsePauliOp:
terms = openfermion_operator.terms

labels = []
coefficients = []

for term, constant in terms.items():
# Default set to identity
operator = list("I" * num_qubits)

# Iterate through PauliSum and replace I with Pauli
for index, pauli in term:
operator[index] = pauli
label = "".join(operator)
labels.append(label)
coefficients.append(constant)

return SparsePauliOp(labels, coefficients)

יתר על כן, מחברת Python זו מכילה קוד לדוגמה מלא להעברת המילטוניאנים מתהליכי עבודה של תוכנות אחרות ל-Qiskit, כולל ההמרה שלמעלה.

עכשיו אמור להיות לך ארסנל של כלים לקבלת ההמילטוניאן שאתה צריך לביצוע חישובי כימיה קוונטית על מחשבים קוונטיים של IBM®.