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

SQD ו-SKQD

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

איסקנדר סיטדיקוב מתאר את הגישה האלגוריתמית בסרטון הבא.

האמילטוניאן

המפתח לבעיה זו הוא אופרטור מתמטי — האמילטוניאן, המייצג את האנרגיה הכוללת של מערכת. למטרות חישוביות, אפשר לחשוב על האמילטוניאן הזה כמטריצה גדולה. הפתרונות שאנחנו מחפשים — ספציפית מצב היסוד של המערכת — הם ערכי העצמה הנמוכים ביותר של מטריצה זו. האתגר הוא שבבעיות מעשיות, מטריצת האמילטוניאן גדולה מאוד. היא גדלה באופן אקספוננציאלי עם גודל המערכת, ומהר מאוד הופכת לגדולה מדי (2n2^n כאשר nn הוא מספר ה-Qubit) אפילו עבור מחשבי-העל החזקים ביותר לאחסון או פתרון ישיר.

H=(H0,0H0,1H0,N1H1,0H1,1H1,N1HN1,0HN1,1HN1,N1)(N=2n)H = \begin{pmatrix} H_{0,0} & H_{0,1} & \cdots & H_{0,N-1} \\ H_{1,0} & H_{1,1} & \cdots & H_{1,N-1} \\ \vdots & \vdots & \ddots & \vdots \\ H_{N-1,0} & H_{N-1,1} & \cdots & H_{N-1,N-1} \end{pmatrix} \quad (N=2^n)

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

(Hi,j)Full HamiltonianProjectH~Projected Hamiltonian=(b1Hb1b1HbLbLHb1bLHbL)Diagonalize(E000EL1)Eigenvalues\underset{\text{Full Hamiltonian}}{\begin{pmatrix} \ddots & \vdots \\ \cdots & H_{i,j} & \cdots \\ & \vdots & \ddots \end{pmatrix}} \quad \xrightarrow{\text{Project}} \quad \underset{\text{Projected Hamiltonian}}{\tilde{H}} = \begin{pmatrix} \langle b_1 | H | b_1 \rangle & \cdots & \langle b_1 | H | b_L \rangle \\ \vdots & \ddots & \vdots \\ \langle b_L | H | b_1 \rangle & \cdots & \langle b_L | H | b_L \rangle \end{pmatrix} \quad \xrightarrow{\text{Diagonalize}} \quad \underset{\text{Eigenvalues}}{\begin{pmatrix} E_0 & & 0 \\ & \ddots & \\ 0 & & E_{L-1} \end{pmatrix}}

לאחר שתת-המרחב הקטן הזה מוגדר על-ידי קבוצת מצבי בסיס {bi}\{|b_i\rangle\}, האמילטוניאן המלא מוקרן עליו כדי ליצור את המטריצה החדשה והקטנה יותר H~\tilde{H}. כל אלמנט במטריצה זו מחושב ממצבי הבסיס של תת-המרחב ומהאמילטוניאן המקורי כפי שמוצג ב-biHbj\langle b_i | H | b_j \rangle. ניתן לאכסן מטריצה קטנה זו בקלות ולבצע עליה אלכסון במחשב קלאסי, וערכי העצמה המתקבלים הם האנרגיות המשוערות שלנו.

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

בסעיפים הבאים נחקור שני אלגוריתמים מתקדמים, SQD ו-SKQD, המנצלים מכניקת קוונטים כדי למצוא ולבנות תת-מרחבים אלה. להעמקה נוספת, קיים קורס מלא ב-IBM Quantum Learning המוקדש לנושאים אלה בפירוט. לצורך הקורס שלנו, נשמור את ההסבר ברמה גבוהה.

אלכסון קוונטי מבוסס-דגימה

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

A schematic of the workflow specific to sample-based quantum diagonalization. The steps include a variational quantum circuit, using measurements to project the Hamiltonian into a subspace, then using a classical optimizer to update variational parameters in the circuit and repeating.

ניתן לפרק את אלגוריתם SQD לשלבים הבאים:

שלב 1: הכנת מצב ה-Ansatz

תהי H=j=1QαjPjH = \sum_{j=1}^Q \alpha_j P_j האמילטוניאן על nn Qubit. בעוד שמצב היסוד האמיתי עשוי להיות מבוסס על כל 2n2^n מצבי הבסיס, SQD הוא יעיל ביותר במקרים שבהם ניתן לקרב היטב את מצב היסוד על-ידי תת-מרחב דליל (קבוצה בגודל פולינומי של מחרוזות-סיביות).

כדי לבנות תת-מרחב זה, אנחנו מתחילים במצב קלט ϕ0|\phi_0\rangle, כמו מצב Hartree-Fock (HF) בכימיה. לאחר מכן אנחנו מפעילים Circuit קוונטי פרמטרי, U(θ)U(\theta), הידוע בשם ה-ansatz.

A diagram showing the overlap of the computational basis states making up the ansatz and those making up the true ground state. Specifically, the image shows that the two regions will have some overlap, but might not perfectly match.

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

שלב 2: דגימת תת-המרחב

על-ידי דגימה מה-Circuit שהוכן על-ידי ה-ansatz, אנחנו מקבלים אוסף של מחרוזות-סיביות, {bj}j=1L\{b_j\}_{j=1}^L. מחרוזות-סיביות אלה מגדירות את הבסיס של תת-המרחב הנבחר שלנו. זמן הריצה הקוונטי לשלב זה נקבע לפי עומק ה-Circuit ומספר הדגימות שנלקחות.

שלב 3: הקרנה ואלכסון קלאסי

בעזרת מחרוזות-הסיביות שנדגמו, אנחנו מקרינים את האמילטוניאן לתת-המרחב שהן פורשות. עבור כל זוג מחרוזות-סיביות (j,k)(j, k), אנחנו מחשבים קלאסית את אלמנט המטריצה H~jk=bjHbk\tilde{H}_{jk} = \langle b_j | H | b_k \rangle. מכיוון שאופרטורי Pauli הם דלילים, שלב זה יעיל קלאסית עבור אמילטוניאנים פיזיקליים. המטריצה הקטנה H~\tilde{H} המתקבלת מאכסנת לאחר מכן במעבד קלאסי כדי לאמוד את מצב היסוד ואת האנרגיה שלו.

שלב 4: אופטימיזציה של ה-ansatz (אופציונלי)

ניתן להפוך את התהליך לאיטרטיבי. על-ידי התייחסות לאנרגיית מצב היסוד המשוערת כאל פונקציית עלות, אנחנו יכולים לבצע אופטימיזציה על פרמטרי ה-Circuit (θ\theta) בשיטות כמו ירידת גרדיאנט כדי לשפר את ה-ansatz, ובתורו, את קירוב האנרגיה באיטרציה הבאה.

היתרונות המרכזיים של SQD

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

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

SQD כבר שימש לאמידת אנרגיית הניתוק של מצב היסוד של N2_2 ולחישוב התכונות האלקטרוניות של אשכולות [2Fe-2S] ו-[4Fe-4S] [2], עם Circuits גדולים עד 77 Qubit ו-10,570 Gate.

בדוק את הבנתך

נכון או לא נכון: ניתן ליישם SQD על מערכות כימיות.

תשובה:

נכון

בדוק את הבנתך

קרא לקבוצת כל מצבי הבסיס החישוביים המרכיבים את ה-ansatz שלך AA. קרא לקבוצת כל מצבי הבסיס החישוביים המרכיבים את מצב היסוד האמיתי של המערכת שלך GG. מה מבין הבאים מתאים ל-ansatz "טוב"? בחר את כל מה שחל.

(a) AGA \subset G \\ (b) AGA \subseteq G\\ (c) GAG \subset A\\ (d) GAG \subseteq A\\

תשובה:

(c) ו-(d)

SKQD (Sample-based Krylov Quantum Diagonalization)

אלגוריתם SKQD (דיאגונליזציה קוונטית של קריילוב מבוססת-דגימה) הוא אלגוריתם קוונטי חזק נוסף מבוסס-דגימה, הבנוי על עקרונות SQD. בעוד מטרתו זהה — למצוא תת-מרחב טוב לדיאגונליזציה — SKQD משתמש בשיטה מובנית יותר ליצירת מחרוזות הביטים, במיוחד עבור בעיות כמו האמילטוניאנים של סריג.

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

שלב 1: בניית תת-מרחב קריילוב באמצעות אבולוציית זמן

התהליך מתחיל במצב התחלתי ϕ0.|\phi_0\rangle. חשוב לציין שאין צורך שמצב זה יהיה בעל "חפיפה טובה" עם מצב היסוד. מספיק שיהיה "גדול פולינומית", כלומר שניתן לתאר אותו בפולינום בגודל המערכת. האלגוריתם עצמו ידחוף את המצב קרוב יותר ויותר למצב היסוד של המערכת. SKQD מפעיל את אופרטור אבולוציית הזמן, eiHte^{-iHt}, לאורכי זמן שונים. כך נוצרת קבוצה של dd מצבים קוונטיים שונים, המוגדרים כ:

ϕj=eiδtjHϕ0,for j=0,1,,d1|\phi_j\rangle = e^{-i \,\delta t j H}|\phi_0\rangle, \quad \text{for } j = 0, 1, \dots, d-1 \quad \text{}

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

שלב 2: דגימה ממצבי בסיס קריילוב

בשלב הבא, אוספים דגימות של מחרוזות ביטים מכל אחד מ-dd המצבים השונים (ϕ0,ϕ1,,ϕd1|\phi_0\rangle, |\phi_1\rangle, \dots, |\phi_{d-1}\rangle) שהוכנו בשלב הקודם. כל מחרוזות הביטים הללו מאוחדות יחד ליצירת הבסיס של תת-המרחב.

שלב 3: השלכה ודיאגונליזציה קלאסית

שלב זה זהה לזה שב-SQD. מחרוזות הביטים שנאספו משמשות להשלכת ההאמילטוניאן המלא לתת-המרחב שהן פורסות. המטריצה הקטנה שמתקבלת, H~\tilde{H}, עוברת דיאגונליזציה על מחשב קלאסי למציאת אנרגיית מצב היסוד.

יתרונות מרכזיים וערבויות של SKQD

הגישה המובנית של SKQD מספקת יתרונות ייחודיים:

  • התכנסות מוכחת: היתרון המרכזי של SKQD הוא הערבות התיאורטית שלו להתכנסות בתנאים ספציפיים ומוגדרים היטב. אם מצב היסוד האמיתי הוא דליל (ניתן לקרב אותו היטב במספר פולינומי של מחרוזות ביטים) ופרק האנרגיה למצב העירור הראשון אינו קטן מדי, הוכח שהשיטה עובדת ביעילות. בתנאים אלה, SKQD מבטיח שהוא ימצא את מחרוזות הביטים הקריטיות המרכיבות את מצב היסוד ויוכל לקרב את אנרגיית מצב היסוד בדיוק גבוה. הדבר דורש רק מספר פולינומי של ניסויים קוונטיים ו-shots. ערבות זו מעמידה את הגישה מבוססת-הדגימה על בסיס תיאורטי קפדני, בדומה לשיטות מבוססות כמו אמידת פאזה קוונטית.

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

בניסויים, SKQD שימש עם עד 70 Qubits ואלפי Gates לחקר מצב היסוד של מודלי אנדרסון מסובכים בעלי 4 פגמים, תוך השגת התאמה מצוינת עם שיטות קלאסיות מתקדמות כמו DMRG.[1]

בדוק את ההבנה שלך

מה בחלק מאלגוריתם SKQD הופך אותו למתאים יותר לבעיות פיזיקליות כמו סריגי ספין מאשר לבעיות כימיות? למה?

תשובה:

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

SQD ו-SKQD כמחשוב הטרוגני

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

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

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

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

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

כפי שמוצג לעיל, ייתכן שתריץ מספר זרימות עבודה בו-זמנית תוך ביצוע הדברים הבאים:

  • שינוי הפרמטרים או המבנה של האנסאץ' כדי למצוא את היעיל ביותר.
  • התחלה ממצבים התחלתיים או תצורות שונות ("אוכלוסיות") כדי להימנע ממינימום מקומיים ולהבטיח תוצאה עמידה יותר.

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

תרגול תכנות

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

מיפוי (mapping.py ו-mapping.sh)

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

mapping.py מגדיר את הפרמטרים לבעיה פיזיקלית ספציפית — במקרה זה, מודל אנדרסון של פגם עם שבעה אתרי אמבטיה (n_bath = 7). הוא בונה את האינטגרלים חד-גופיים (h1e) ודו-גופיים (h2e) המייצגים את ההאמילטוניאן של המערכת.


...

n_bath = 7 # number of bath sites

...

# One body matrix elements in the "position" basis
h1e = -t * np.diag(np.ones(n_bath), k=1) - t * np.diag(np.ones(n_bath), k=-1)
h1e[impurity_index, impurity_index + 1] = -V
h1e[impurity_index + 1, impurity_index] = -V
h1e[impurity_index, impurity_index] = eps

# Two body matrix elements in the "position" basis
h2e = np.zeros((n_bath + 1, n_bath + 1, n_bath + 1, n_bath + 1))
h2e[impurity_index, impurity_index, impurity_index, impurity_index] = U

...

# The one-body time evolution
free_fermion_evolution = ffsim.qiskit.OrbitalRotationJW(n_modes, Utar)

# The two-body time evolution
def append_diagonal_evolution(dt, U, impurity_qubit, num_orb, q_circuit):
"""Append two-body time evolution to a quantum circuit."""
if U != 0:
q_circuit.append(
CPhaseGate(-dt / 2 * U),
[impurity_qubit, impurity_qubit + num_orb],
)

לאחר מכן הסקריפט מייצר את ה-Circuits הקוונטיים הנדרשים לאלגוריתם SKQD. הוא מתחיל ביצירת מצב התחלתי (initial_state) ואז מפעיל אופרטורי אבולוציית זמן למספרים משתנים של צעדים (d = 8) כדי לייצר את מצבי בסיס קריילוב השונים, ϕj=(eiHt)jϕ0|\phi_j\rangle = (e^{-iHt})^j |\phi_0\rangle.


# The reference state
def initial_state(q_circuit, norb, nocc):
"""Prepare an initial state."""
for i in range(nocc):
q_circuit.append(XGate(), [i])
q_circuit.append(XGate(), [norb + i])
rot = XXPlusYYGate(np.pi / 2, -np.pi / 2)

for i in range(3):
for j in range(nocc - i - 1, nocc + i, 2):
q_circuit.append(rot, [j, j + 1])
q_circuit.append(rot, [norb + j, norb + j + 1])
q_circuit.append(rot, [j + 1, j + 2])
q_circuit.append(rot, [norb + j + 1, norb + j + 2])

...

# Generate the initial state
qubits = QuantumRegister(2 * n_modes, name="q")
init_state = QuantumCircuit(qubits)
initial_state(init_state, n_modes, n_modes // 2)

...

d = 8 # Number of Krylov basis states
circuits = []
for i in range(d):
circ = init_state.copy()
circuits.append(circ)
for _ in range(i):
append_diagonal_evolution(dt, U, impurity_index, n_modes, circ)
circ.append(free_fermion_evolution, qubits)
append_diagonal_evolution(dt, U, impurity_index, n_modes, circ)
circ.measure_all()

print(circuits[0].draw(scale=0.4, fold=-1))

הסקריפט שומר את רשימת 8 ה-Circuits שנוצרו (כל אחד עם מדידות מצורפות) לקובץ בשם circuits.qpy.

mapping.sh הוא סקריפט אצווה של Slurm המשמש להגשת משרת mapping.py. מאחר שמדובר בחישוב קלאסי, הוא מבקש משאבים ממחיצה רגילה של CPU (--partition=normal).

#!/bin/bash
#
#SBATCH --job-name=sqd-mapping
#SBATCH --output=sqd-mapping.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/mapping.py

אופטימיזציה (optimization.py ו-optimization.sh)

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

ב-optimization.py, הסקריפט טוען תחילה את קובץ circuits.qpy שנוצר בשלב המיפוי ומביא מידע על משאבי קוונטום באמצעות QRMI(), מנהל משאבי קוונטום. לאחר מכן הוא משתמש ב-generate_preset_pass_manager של Qiskit עם רמת אופטימיזציה גבוהה (optimization_level=3) כדי להמיר את ה-Circuits הלוגיים המופשטים ל-Circuits של ארכיטקטורת מערכת ההוראות (ISA). תהליך זה כותב מחדש את ה-Circuits תוך שימוש ב-Gates הטבעיות של החומרה ומבצע עליהם אופטימיזציה לצמצום העומק ומזעור שגיאות.


...
qrmi = QRMI()
resources = qrmi.resources()
quantum_resource = resources[0]
target = quantum_resource.target

pass_manager = generate_preset_pass_manager(
optimization_level=3,
target=target
)
isa_circuits = pass_manager.run(circuits)

ה-Circuits שעברו טרנספילציה ומוכנים לחומרה נשמרים לקובץ חדש, isa_circuits.qpy.

בדומה לסקריפט המיפוי, משרת Slurm זו גם רצה על מחיצה קלאסית של CPU (--partition=normal), מאחר שטרנספילציה היא משימה קלאסית.

#!/bin/bash
#
#SBATCH --job-name=sqd-mapping
#SBATCH --output=sqd-mapping.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/mapping.py

ביצוע (execution.py ו-execution.sh)

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

execution.py טוען את קובץ isa_circuits.qpy המאופטם, מאתחל Primitive של SamplerV2 המחובר למשאב קוונטי. לאחר מכן הוא קורא ל-sampler.run() כדי להריץ את ה-Circuits על ה-QPU למספר shots מוגדר (shots=500).


...

qrmi = QRMI()
resources = qrmi.resources()
quantum_resource = resources[0]

# Sample from the circuits
noisy_sampler = Sampler(quantum_resource)
job = noisy_sampler.run(isa_circuits, shots=500)

בסיום הביצוע, התוצאות שנמדדו (מחרוזות הביטים) מכל ה-Circuits נאספות ומשולבות, וספירותיהן נשמרות לקובץ counts.json.

סקריפט Slurm execution.sh שונה מהאחרים בשלב זה. הוא מבקש להריץ על מחיצת הקוונטום (--partition=quantum) ומבקש באופן ספציפי QPU אחד (--gres=qpu:1).

#!/bin/bash
#
#SBATCH --job-name=sqd-execution
#SBATCH --output=sqd-execution.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=quantum
#SBATCH --gres=qpu:1

srun python /data/ch4/sqd/execution.py

עיבוד-לאחר (postprocessing.py ו-postprocessing.sh)

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

תוכנית postprocessing.py קוראת תחילה את קובץ counts.json המכיל את תוצאות המדידה. לאחר מכן היא בונה מחדש את ההאמילטוניאן של מודל אנדרסון (תוך שימוש באותם פרמטרים כמו ב-mapping.py). לאחר מכן היא מעבירה את מחרוזות הביטים שנמדדו ואת הגדרת ההאמילטוניאן לפונקציה diagonalize_fermionic_hamiltonian. פונקציה זו מבצעת את לוגיית ה-SKQD המרכזית: היא משתמשת במחרוזות הביטים לבניית ההאמילטוניאן המושלך H~\tilde{H} ומבצעת עליו דיאגונליזציה למציאת אנרגיית מצב היסוד.


...

def callback(results: list[SCIResult]):
result_history.append(results)
iteration = len(result_history)
print(f"Iteration {iteration}")
for i, result in enumerate(results):
print(f"\tSubsample {i}")
print(f"\t\tEnergy: {result.energy}")
print(f"\t\tSubspace dimension: {np.prod(result.sci_state.amplitudes.shape)}")

rng = np.random.default_rng(24)
result = diagonalize_fermionic_hamiltonian(
h1e,
h2e,
bit_array,
samples_per_batch=300,
norb=n_modes,
nelec=nelec,
num_batches=3,
max_iterations=10,
symmetrize_spin=True,
callback=callback,
seed=rng,
)

לבסוף, זה מדפיס את אנרגיית SKQD שחושבה ומשווה אותה לאנרגיה המדויקת הידועה עבור בעיה זו, ומציג את השגיאה המוחלטת הסופית של החישוב.

סקריפט המשרה האחרון רץ על מחיצה קלאסית (--partition=normal), מאחר שכל הניתוח הוא קלאסי. עבור תת-מרחבים גדולים, שלב זה עשוי לדרוש משאבי HPC קלאסיים רבים יותר.

#!/bin/bash
#
#SBATCH --job-name=sqd-postprocessing
#SBATCH --output=sqd-postprocessing.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/postprocessing.py

סיכום

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

כדי לחקור עוד מקרי שימוש ואלגוריתמים, עיין בתיעוד ובמדריכים שלנו ב-IBM Quantum Platform, ודאג לבקר במשאבים המשותפים בשיעור הבא לקבלת מידע נוסף על אלגוריתמים ותוכנות עבור מדעני מחשוב ומנהלי מרכזי נתונים כאחד.

מקורות

[1] Quantum-Centric Algorithm for Sample-Based Krylov Diagonalization. https://arxiv.org/abs/2501.09702