שיטות קומפי לציה למעגלים של סימולציית המילטון
שימוש משוער ב-QPU: לא בוצעה הרצה במדריך זה כיוון שהוא מתמקד בתהליך הטרנספילציה.
רקע
קומפילציה של מעגלים קוונטיים היא שלב קריטי בזרימת העבודה של מחשוב קוונטי. היא כוללת המרה של אלגוריתם קוונטי ברמה גבוהה למעגל קוונטי פיזי המתאים למגבלות החומרה הקוונטית היעד. קומפילציה אפקטיבית יכולה להשפיע משמעותית על הביצועים של אלגוריתמים קוונטיים על ידי הפחתת עומק המעגל, מספר השערים וזמן ההרצה. מדריך זה חוקר שלוש גישות שונות לקומפילציה של מעגלים קוונטיים ב-Qiskit, ומציג את החוזקות והיישומים שלהן דרך דוגמאות מעשיות.
מטרת המדריך היא ללמד משתמשים כיצד ליישם ולהעריך שלוש שיטות קומפילציה ב-Qiskit: ה-transpiler של SABRE, ה-transpiler המונע AI, והתוסף Rustiq. משתמשים ילמדו כיצד להשתמש בכל שיטה באופן אפקטיבי וכיצד לבצע בנצ'מרק על הביצועים שלהן על פני מעגלים קוונטיים שונים. בסוף המדריך, משתמשים יוכלו לבחור ולהתאים אסטרטגיות קומפילציה על בסיס מטרות אופטימיזציה ספציפיות כגון הפחתת עומק המעגל, מזעור מספר השערים או שיפור זמן הריצה.
מה תלמדו
- כיצד להשתמש ב-transpiler של Qiskit עם SABRE לאופטימיזציה של פריסה וניתוב.
- כיצד למנף את ה-AI transpiler לאופטימיזציה מתקדמת ואוטומטית של מעגלים.
- כיצד להשתמש בתוסף Rustiq עבור מעגלים הדורשים סינתזה מדויקת של פעולות, במיוחד במשימות סימולציית המילטון.
מדריך זה משתמש בשלושה מעגלי דוגמה העוקבים אחר זרימת העבודה של תבניות Qiskit כדי להמחיש את הביצועים של כל שיטת קומפילציה. בסוף המדריך, משתמשים יהיו מצוידים לבחור את אסטרטגיית הקומפילציה המתאימה על בסיס הדרישות והמגבלות הספציפיות שלהם.
סקירה כללית של שיטות קומפילציה
1. Qiskit transpiler עם SABRE
ה-transpiler של Qiskit משתמש באלגוריתם SABRE (SWAP-based BidiREctional heuristic search) לאופטימיזציה של פריסה וניתוב מעגל. SABRE מתמקד במזעור שערי SWAP והשפעתם על עומק המעגל תוך עמידה במגבלות קישוריות החומרה. שיטה זו היא רב-תכליתית ביותר ומתאימה לאופטימיזציה של מעגלים למטרה כללית, ומספקת איזון בין ביצועים לזמן חישוב. כדי לנצל את השיפורים האחרונים ב-SABRE, המפורטים ב-[1], ניתן להגדיל את מספר הניסויים (לדוגמה, layout_trials=400, swap_trials=400). למטרות מדריך זה, נשתמש בערכי ברירת המחדל למספר הניסויים כדי להשוות ל-transpiler ברירת המחדל של Qiskit. היתרונות וחקירת הפרמטרים של SABRE מכוסים ב-מדריך מעמיק נפרד.
2. AI transpiler
ה-transpiler המונע AI ב-Qiskit משתמש בלמידת מכונה כדי לחזות אסטרטגיות טרנספילציה אופטימליות על ידי ניתוח דפוסים במבנה המעגל ומגבלות החומרה כדי לבחור את רצף האופטימיזציות הטוב ביותר עבור קלט נתון. שיטה זו אפקטיבית במיוחד עבור מעגלים קוונטיים בקנה מידה גדול, ומציעה דרגה גבוהה של אוטומציה והסתגלות לסוגי בעיות מגוונים. בנוסף לאופטימיזציה כללית של מעגלים, ניתן להשתמש ב-AI transpiler עם ה-pass AIPauliNetworkSynthesis, המכוון למעגלי רשת Pauli — בלוקים המורכבים משערים H, S, SX, CX, RX, RY ו-RZ — ומיישם גישת סינתזה מבוססת למידה מחזקת. למידע נוסף על ה-AI transpiler ואסטרטגיות הסינתזה שלו, ראה [2] ו-[3].
3. תוסף Rustiq
תוסף Rustiq מציג טכניקות סינתזה מתקדמות במיוחד עבור פעולות PauliEvolutionGate, המייצגות סיבובי Pauli המשמשים בדרך כלל בדינמיקה של Trotterization. תוסף זה הוא בעל ערך עבור מעגלים המיישמים סימולציית המילטון, כגון אלה המשמשים בבעיות כימיה קוונטית ופיזיקה, שבהן סיבובי Pauli מדויקים חיוניים לסימולציה אפקטיבית של המילטוניאנים של הבעיה. Rustiq מציע סינתזה מדויקת ובעומק נמוך של מעגלים עבור פעולות מיוחדות אלה. לפרטים נוספים על היישום והביצועים של Rustiq, ראה ב-[4].
על ידי חקירה לעומק של שיטות קומפילציה אלה, מדריך זה מספק למשתמשים כלים לשיפור הביצועים של המעגלים הקוונטיים שלהם, סולל את הדרך לחישובים קוונטיים יעילים ומעשיים יותר.
דרישות
לפני תחילת מדריך זה, ודא שיש לך את הדברים הבאים מותקנים:
- Qiskit SDK v1.3 ומעלה, עם תמיכה ב-ויזואליזציה
- Qiskit Runtime v0.28 ומעלה (
pip install qiskit-ibm-runtime) - Qiskit IBM Transpiler (
pip install qiskit-ibm-transpiler) - Qiskit AI Transpiler local mode (
pip install qiskit_ibm_ai_local_transpiler) - ספריית גרפים Networkx (
pip install networkx)
הגדרה
# Added by doQumentation — required packages for this notebook
!pip install -q IPython matplotlib numpy pandas qiskit qiskit-ibm-runtime qiskit-ibm-transpiler requests
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.circuit.library import (
efficient_su2,
PauliEvolutionGate,
)
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
from collections import Counter
from IPython.display import display
import time
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import json
import requests
import logging
# Suppress noisy loggers
logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.ERROR)
seed = 42 # Seed for reproducibility
חלק 1: מעגל SU2 יעיל
שלב 1: מיפוי קלטים קלאסיים לבעיה קוונטית
בחלק זה, אנחנו חוקרים את מעגל efficient_su2, ansatz יעיל לחומרה המשמש בדרך כלל באלגוריתמים קוונטיים וריאציוניים (כגון VQE) ומשימות למידת מכונה קוונטיות. המעגל מורכב משכבות מתחלפות של סיבובים של qubit יחיד ושערי שזירה המסודרים בדפוס מעגלי, תוכננו לחקור את מרחב המצבים הקוונטיים באופן אפקטיבי תוך שמירה על עומק סביר.
נתחיל בבניית מעגל efficient_su2 אחד כדי להדגים כיצד להשוות שיטות קומפילציה שונות. לאחר חלק 1, נרחיב את הניתוח שלנו לסט גדול יותר של מעגלים, ונאפשר בנצ'מרק מקיף להערכת הביצועים של טכניקות קומפילציה שונות.
qubit_size = list(range(10, 101, 10))
qc_su2_list = [
efficient_su2(n, entanglement="circular", reps=1)
.decompose()
.copy(name=f"SU2_{n}")
for n in qubit_size
]
# Draw the first circuit
qc_su2_list[0].draw(output="mpl")
שלב 2: אופטימיזציה של הבעיה להרצה על חומרה קוונטית
שלב זה הוא המיקוד העיקרי של המדריך. כאן, המטרה שלנו היא לבצע אופטימיזציה של מעגלים קוונטיים להרצה יעילה על חומרה קוונטית אמיתית. המטרה העיקרית שלנו היא להפחית את עומק המעגל ומספר השערים, שהם גורמים מפתח בשיפור נאמנות ההרצה והפחתת רעש החומרה.
- SABRE transpiler: משתמש ב-transpiler ברירת המחדל של Qiskit עם אלגוריתם הפריסה והניתוב של SABRE.
- AI transpiler (מצב מקומי): ה-transpiler סטנדרטי המונע AI המשתמש בהיסק מקומי ובאסטרטגיית הסינתזה ברירת המחדל.
- תוסף Rustiq: תוסף transpiler המיועד לקומפילציה בעומק נמוך המותאמת למשימות סימולציית המילטון.
מטרת השלב היא להשוות את התוצאות של שיטות אלה במונחים של עומק המעגל המטרנספל ומספר השערים. מדד חשוב נוסף שאנו מביאים בחשבון הוא זמן ריצת הטרנספילציה. על ידי ניתוח מדדים אלה, נוכל להעריך את החוזקות היחסיות של כל שיטה ולקבוע א יזו מייצרת את המעגל היעיל ביותר להרצה על החומרה הנבחרת.
הערה: עבור דוגמת מעגל SU2 הראשונית, נשווה רק את ה-SABRE transpiler ל-AI transpiler ברירת המחדל. עם זאת, בבנצ'מרק הבא באמצעות מעגלי Hamlib, נשווה את כל שלוש שיטות הטרנספילציה.
# QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token="<YOUR-API-KEY>", overwrite=True, set_as_default=True)
service = QiskitRuntimeService(channel="ibm_quantum_platform")
backend = service.backend("ibm_torino")
print(f"Using backend: {backend}")
qiskit_runtime_service._get_crn_from_instance_name:WARNING:2025-07-30 21:46:30,843: Multiple instances found. Using all matching instances.
Using backend: <IBMBackend('ibm_torino')>
Qiskit transpiler עם SABRE:
pm_sabre = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=seed
)
AI transpiler:
# Standard AI transpiler pass manager, using the local mode
pm_ai = generate_ai_pass_manager(
backend=backend, optimization_level=3, ai_optimization_level=3
)
תוסף Rustiq:
hls_config = HLSConfig(
PauliEvolution=[
(
"rustiq",
{
"nshuffles": 400,
"upto_phase": True,
"fix_clifford": True,
"preserve_order": False,
"metric": "depth",
},
)
]
)
pm_rustiq = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
hls_config=hls_config,
seed_transpiler=seed,
)
טרנספל ולכידת מדדים
כדי להשוות את הביצועים של שיטות הקומפילציה, אנחנו מגדירים פונקציה שמטרנספלת את מעגל הקלט ולוכדת מדדים רלוונטיים באופן עקבי. זה כולל את עומק המעגל הכולל, מספר השערים הכולל וזמן הטרנספילציה.
בנוסף למדדים סטנדרטיים אלה, אנחנו גם רושמים את עומק שער ה-2-qubit, שהוא מדד חשוב במיוחד להערכת הרצה על חומרה קוונטית. בניגוד לעומק כולל, הכולל את כל השערים, עומק ה-2-qubit משקף בצורה מדויקת יותר את משך ההרצה בפועל של המעגל על החומרה. הסיבה לכך היא ששערי 2-qubit בדרך כלל שולטים בתקציב הזמן והשגיאות ברוב המכשירים הקוונטיים. ככזה, מזעור עומק ה-2-qubit הוא קריטי לשיפור הנאמנות והפחתת השפעות הדה-קוהרנטיות במהלך ההרצה.
נשתמש בפונקציה זו כדי לנתח את הביצועים של שיטות הקומפילציה השונות על פני מספר מעגלים.
def capture_transpilation_metrics(
results, pass_manager, circuits, method_name
):
"""
Capture transpilation metrics for a list of circuits and stores the results in a DataFrame.
Args:
results (pd.DataFrame): DataFrame to store the results.
pass_manager: Pass manager used for transpilation.
circuits (list): List of quantum circuits to transpile.
method_name (str): Name of the transpilation method.
Returns:
list: List of transpiled circuits.
"""
transpiled_circuits = []
for i, qc in enumerate(circuits):
# Transpile the circuit
start_time = time.time()
transpiled_qc = pass_manager.run(qc)
end_time = time.time()
# Needed for AI transpiler to be consistent with other methods
transpiled_qc = transpiled_qc.decompose(gates_to_decompose=["swap"])
# Collect metrics
transpilation_time = end_time - start_time
circuit_depth = transpiled_qc.depth(
lambda x: x.operation.num_qubits == 2
)
circuit_size = transpiled_qc.size()
# Append results to DataFrame
results.loc[len(results)] = {
"method": method_name,
"qc_name": qc.name,
"qc_index": i,
"num_qubits": qc.num_qubits,
"ops": transpiled_qc.count_ops(),
"depth": circuit_depth,
"size": circuit_size,
"runtime": transpilation_time,
}
transpiled_circuits.append(transpiled_qc)
print(
f"Transpiled circuit index {i} ({qc.name}) in {transpilation_time:.2f} seconds with method {method_name}, "
f"depth {circuit_depth}, and size {circuit_size}."
)
return transpiled_circuits
results_su2 = pd.DataFrame(
columns=[
"method",
"qc_name",
"qc_index",
"num_qubits",
"ops",
"depth",
"size",
"runtime",
]
)
tqc_sabre = capture_transpilation_metrics(
results_su2, pm_sabre, qc_su2_list, "sabre"
)
tqc_ai = capture_transpilation_metrics(results_su2, pm_ai, qc_su2_list, "ai")
Transpiled circuit index 0 (SU2_10) in 0.06 seconds with method sabre, depth 13, and size 167.
Transpiled circuit index 1 (SU2_20) in 0.24 seconds with method sabre, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 10.72 seconds with method sabre, depth 72, and size 627.
Transpiled circuit index 3 (SU2_40) in 16.16 seconds with method sabre, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 76.89 seconds with method sabre, depth 77, and size 855.
Transpiled circuit index 5 (SU2_60) in 86.12 seconds with method sabre, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 94.46 seconds with method sabre, depth 79, and size 1085.
Transpiled circuit index 7 (SU2_80) in 69.05 seconds with method sabre, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 88.25 seconds with method sabre, depth 105, and size 1420.
Transpiled circuit index 9 (SU2_100) in 83.80 seconds with method sabre, depth 100, and size 1499.
Transpiled circuit index 0 (SU2_10) in 0.17 seconds with method ai, depth 10, and size 168.
Transpiled circuit index 1 (SU2_20) in 0.29 seconds with method ai, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 13.56 seconds with method ai, depth 36, and size 548.
Transpiled circuit index 3 (SU2_40) in 15.95 seconds with method ai, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 80.70 seconds with method ai, depth 54, and size 823.
Transpiled circuit index 5 (SU2_60) in 75.99 seconds with method ai, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 64.96 seconds with method ai, depth 74, and size 1087.
Transpiled circuit index 7 (SU2_80) in 68.25 seconds with method ai, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 75.07 seconds with method ai, depth 90, and size 1404.
Transpiled circuit index 9 (SU2_100) in 63.97 seconds with method ai, depth 100, and size 1499.
הצגת תוצאות הטרנספילציה של אחד המעגלים.
print("Sabre transpilation")
display(tqc_sabre[0].draw("mpl", fold=-1, idle_wires=False))
print("AI transpilation")
display(tqc_ai[0].draw("mpl", fold=-1, idle_wires=False))
Sabre transpilation

AI transpilation

טבלת תוצאות:
summary_su2 = (
results_su2.groupby("method")[["depth", "size", "runtime"]]
.mean()
.round(2)
)
print(summary_su2)
results_su2
depth size runtime
method
ai 56.4 852.5 45.89
sabre 64.6 864.9 52.57
method qc_name qc_index num_qubits ops \
0 sabre SU2_10 0 10 {'rz': 81, 'sx': 70, 'cz': 16}
1 sabre SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
2 sabre SU2_30 2 30 {'sx': 295, 'rz': 242, 'cz': 90}
3 sabre SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
4 sabre SU2_50 4 50 {'rz': 402, 'sx': 367, 'cz': 86}
5 sabre SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
6 sabre SU2_70 6 70 {'rz': 562, 'sx': 441, 'cz': 82}
7 sabre SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
8 sabre SU2_90 8 90 {'rz': 721, 'sx': 585, 'cz': 114}
9 sabre SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}
10 ai SU2_10 0 10 {'rz': 81, 'sx': 71, 'cz': 16}
11 ai SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
12 ai SU2_30 2 30 {'sx': 243, 'rz': 242, 'cz': 63}
13 ai SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
14 ai SU2_50 4 50 {'rz': 403, 'sx': 346, 'cz': 74}
15 ai SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
16 ai SU2_70 6 70 {'rz': 563, 'sx': 442, 'cz': 82}
17 ai SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
18 ai SU2_90 8 90 {'rz': 721, 'sx': 575, 'cz': 108}
19 ai SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}
depth size runtime
0 13 167 0.058845
1 20 299 0.238217
2 72 627 10.723922
3 40 599 16.159262
4 77 855 76.886604
5 60 899 86.118255
6 79 1085 94.458287
7 80 1199 69.048184
8 105 1420 88.254809
9 100 1499 83.795482
10 10 168 0.171532
11 20 299 0.291691
12 36 548 13.555931
13 40 599 15.952733
14 54 823 80.702141
15 60 899 75.993404
16 74 1087 64.960162
17 80 1199 68.253280
18 90 1404 75.072412
19 100 1499 63.967446
גרף תוצאות
כפי שאנו מגדירים פונקציה ללכידת מדדים באופן עקבי, נגדיר גם אחת לציור המדדים בגרף. כאן, נציג את עומק ה-2-qubit, מספר השערים וזמן הריצה עבור כל שיטת קומפילציה על פני המעגלים.
def plot_transpilation_metrics(results, overall_title, x_axis="qc_index"):
"""
Plots transpilation metrics (depth, size, runtime) for different transpilation methods.
Parameters:
results (DataFrame): Data containing columns ['num_qubits', 'method', 'depth', 'size', 'runtime']
overall_title (str): The title of the overall figure.
x_axis (str): The x-axis label, either 'num_qubits' or 'qc_index'.
"""
fig, axs = plt.subplots(1, 3, figsize=(24, 6))
metrics = ["depth", "size", "runtime"]
titles = ["Circuit Depth", "Circuit Size", "Transpilation Runtime"]
y_labels = ["Depth", "Size (Gate Count)", "Runtime (s)"]
methods = results["method"].unique()
colors = plt.colormaps["tab10"]
markers = ["o", "^", "s", "D", "P", "*", "X", "v"]
color_list = [colors(i % colors.N) for i in range(len(methods))]
color_map = {method: color_list[i] for i, method in enumerate(methods)}
marker_map = {
method: markers[i % len(markers)] for i, method in enumerate(methods)
}
jitter_factor = 0.1 # Small x-axis jitter for visibility
handles, labels = [], [] # Unique handles for legend
# Plot each metric
for i, metric in enumerate(metrics):
for method in methods:
method_data = results[results["method"] == method]
# Introduce slight jitter to avoid exact overlap
jitter = np.random.uniform(
-jitter_factor, jitter_factor, len(method_data)
)
scatter = axs[i].scatter(
method_data[x_axis] + jitter,
method_data[metric],
color=color_map[method],
label=method,
marker=marker_map[method],
alpha=0.7,
edgecolors="black",
s=80,
)
if method not in labels:
handles.append(scatter)
labels.append(method)
axs[i].set_title(titles[i])
axs[i].set_xlabel(x_axis)
axs[i].set_ylabel(y_labels[i])
axs[i].grid(axis="y", linestyle="--", alpha=0.7)
axs[i].tick_params(axis="x", rotation=45)
axs[i].set_xticks(sorted(results[x_axis].unique()))
fig.suptitle(overall_title, fontsize=16)
fig.legend(
handles=handles,
labels=labels,
loc="upper right",
bbox_to_anchor=(1.05, 1),
)
plt.tight_layout()
plt.show()
plot_transpilation_metrics(
results_su2, "Transpilation Metrics for SU2 Circuits", x_axis="num_qubits"
)

ניתוח תוצאות קומפילציה של מעגל SU2
בניסוי זה, אנחנו משווים שתי שיטות טרנספילציה — ה-SABRE transpiler של Qiskit וה-AI-powered transpiler — על סט של מעגלי efficient_su2. מכיוון שמעגלים אלה אינם כוללים פעולות PauliEvolutionGate, תוסף Rustiq אינו נכלל בהשוואה זו.
בממוצע, ה-AI transpiler מבצע טוב יותר במונחים של עומק המעגל, עם שיפור של יותר מ-10% על פני הטווח המלא של מעגלי SU2. עבור מספר השערים (גודל המעגל) וזמן ריצת הטרנספילציה, שתי השיטות מניבות תוצאות דומות באופן כללי.
עם זאת, בדיקת נקודות הנתונים הבודדות מגלה תובנה עמוקה יותר:
- עבור רוב גדלי ה-qubit, גם SABRE וגם AI מייצרים תוצאות כמעט זהות, מה שמציע שבמקרים רבים, שתי השיטות מתכנסות לפתרונות יעילים באופן דומה.
- עבור גדלי מעגל מסוימים, במיוחד ב-30, 50, 70 ו-90 qubits, ה-AI transpiler מוצא מעגלים רדודים משמעותית יותר מאשר SABRE. זה מצביע על כך שהגישה המבוססת למידה של AI מסוגלת לגלות פריסות אופטימליות יותר או נתיבי ניתוב במקרים שבהם ההיוריסטיקה של SABRE לא.
התנהגות זו מדגישה מסקנה חשובה:
בעוד SABRE ו-AI לעתים קרובות מייצרים תוצאות ניתנות להשוואה, ה-AI transpiler יכול מדי פעם לגלות פתרונות טובים בהרבה, במיוחד במונחים של עומק, מה שיכול להוביל לביצועים משופרים משמעותית על החומרה.
חלק 2: מעגל סימולציית המילטון
שלב 1: חקירת מעגלים עם PauliEvolutionGate
בחלק זה, אנחנו חוקרים מעגלים קוונטיים הבנויים באמצעות PauliEvolutionGate, המאפשר סימולציה יעילה של המילטוניאנים. ננתח כיצד שיטות קומפילציה שונות מבצעות אופטימיזציה למעגלים אלה על פני המילטוניאנים שונים.
המילטוניאנים המשמשים בבנצ'מרק
המילטוניאנים המשמשים בבנצ'מרק זה מתארים אינטראקציות זוגיות בין qubits, כולל מונחים כגון , ו-. המילטוניאנים אלה משמשים בדרך כלל בכימיה קוונטית, פיזיקת חומר מעובה ומדעי החומרים, שבהם הם מדגימים מערכות של חלקיקים מקיימי אינטראקציה.
לעיון, משתמשים יכולים לחקור סט רחב יותר של המילטוניאנים במאמר זה: Efficient Hamiltonian Simulation on Noisy Quantum Devices.