انتقل إلى المحتوى الرئيسي

مقدمة إلى المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي في Qiskit

تقدير الاستخدام: 5 دقائق على IBM Heron (ملاحظة: هذا تقدير فقط. قد يختلف وقت تشغيلك الفعلي.)

نتائج التعلم

بعد إتمام هذا البرنامج التعليمي، سيفهم المستخدمون:

  • كيفية استخدام المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي (generate_ai_pass_manager) كبديل مباشر للمُحوِّل القياسي
  • كيفية مقارنة المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي بالمُحوِّل الافتراضي من حيث عمق البوابات ثنائية البتات الكمومية وعدد البوابات ووقت التحويل البرمجي
  • كيفية استخدام الدوائر المرآتية لتقييم جودة التحويل البرمجي من خلال تنفيذها على الأجهزة الحقيقية

المتطلبات الأساسية

نقترح على المستخدمين الإلمام بالموضوعات التالية قبل البدء في هذا البرنامج التعليمي:

الخلفية

يُقدِّم المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي في Qiskit مسارات تحويل برمجي قائمة على تعلم الآلة قادرة على إنتاج دوائر أقصر وأكثر ملاءمةً للأجهزة مقارنةً بالأساليب الاستدلالية التقليدية كـ SABRE. تتراكم الدوائر الأقصر ضوضاءً أقل، مما يُحسِّن جودة النتائج مباشرةً على الأجهزة الكمومية الحقيقية.

في هذا البرنامج التعليمي، نُقارن بين استراتيجيتَي تحويل برمجي:

الاستراتيجيةواجهة برمجة التطبيقات
الافتراضيةgenerate_preset_pass_manager(optimization_level=3, ...)
الذكاء الاصطناعيgenerate_ai_pass_manager(optimization_level=1, ai_optimization_level=3, ...)

نقيس ثلاثة مقاييس لكل استراتيجية: عمق بوابات البتتين الكموميتين، وإجمالي عدد البوابات، ووقت تشغيل التحويل البرمجي.

معايير أداء المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي

في اختبارات المعايير، أنتج المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي باستمرار دوائر أقل عمقًا وأعلى جودةً مقارنةً بمُحوِّل Qiskit القياسي. استخدمنا في هذه الاختبارات استراتيجية مدير المسارات الافتراضية في Qiskit، المهيَّأة باستخدام generate_preset_pass_manager. وفي حين تكون هذه الاستراتيجية الافتراضية فعّالة في أغلب الأحيان، قد تُعاني مع الدوائر الأكبر حجمًا أو الأكثر تعقيدًا. في المقابل، حققت المسارات المدعومة بالذكاء الاصطناعي تخفيضًا بنسبة 24% في المتوسط في أعداد بوابات البتتين الكموميتين، وتخفيضًا بنسبة 36% في عمق الدائرة للدوائر الكبيرة (100+ بت كمومي) عند التحويل البرمجي إلى طبولوجيا heavy-hex لأجهزة IBM Quantum®. للمزيد من المعلومات حول هذه المعايير، راجع هذه المدونة.

معايير المُحوِّل البرمجي المدعوم بالذكاء الاصطناعي

يستكشف هذا البرنامج التعليمي الفوائد الرئيسية لمسارات الذكاء الاصطناعي وكيفية مقارنتها بالأساليب التقليدية.

المتطلبات

قبل البدء في هذا البرنامج التعليمي، تأكد من تثبيت ما يلي:

  • Qiskit SDK الإصدار 2.0 أو أحدث، مع دعم التصوير البياني
  • Qiskit Runtime (pip install qiskit-ibm-runtime) الإصدار 0.22 أو أحدث
  • Qiskit IBM Transpiler مع وضع الذكاء الاصطناعي المحلي (pip install 'qiskit-ibm-transpiler[ai-local-mode]')
  • Qiskit Aer (pip install qiskit-aer)

الإعداد

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib qiskit qiskit-aer qiskit-ibm-runtime qiskit-ibm-transpiler
from qiskit import QuantumCircuit
from qiskit.circuit.random import random_circuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error
import matplotlib.pyplot as plt
from statistics import mean, stdev
import time
import logging

seed = 42

def transpile_with_metrics(pass_manager, circuit):
"""Transpile a circuit and return the result along with key metrics."""
start = time.time()
qc_out = pass_manager.run(circuit)
elapsed = time.time() - start

depth_2q = qc_out.depth(lambda x: x.operation.num_qubits == 2)
gate_count = qc_out.size()

return qc_out, {
"depth_2q": depth_2q,
"gate_count": gate_count,
"time_s": round(elapsed, 3),
}

def remap_to_contiguous(tqc):
"""Remap a transpiled circuit to use contiguous qubit indices.

Transpiled circuits target specific physical qubits (e.g., qubit 45, 67)
on a large backend. This remaps them to 0, 1, 2, ... so Aer only
simulates the active qubits."""
active = sorted(
{tqc.find_bit(q).index for inst in tqc.data for q in inst.qubits}
)
qubit_map = {old: new for new, old in enumerate(active)}
new_qc = QuantumCircuit(len(active))
for inst in tqc.data:
old_indices = [tqc.find_bit(q).index for q in inst.qubits]
new_qc.append(inst.operation, [qubit_map[i] for i in old_indices])
return new_qc

def build_mirror_circuit(tqc, simulate=True):
"""Build a mirror circuit: U followed by U-dagger, with measurements.

The expected output is always |0...0>, so measuring the survival
probability reveals how much noise each transpilation strategy adds.

Args:
tqc: A transpiled circuit.
simulate: If True (default), remap to contiguous qubits so Aer
only simulates the active qubits. If False, keep the full
physical layout for hardware execution."""
if simulate:
tqc = remap_to_contiguous(tqc)
mirror = tqc.compose(tqc.inverse())
mirror.measure_all()
return mirror

def print_summary(results):
"""Print a summary of each metric as mean +/- stdev across all circuits,
along with the mean percentage improvement of AI over Default."""
metrics = [
("Depth 2Q", "Depth 2Q (Default)", "Depth 2Q (AI)"),
("Gate Count", "Gate Count (Default)", "Gate Count (AI)"),
("Time (s)", "Time (Default)", "Time (AI)"),
]
header = (
f"{'Metric':<12}{'Default (mean +/- std)':>24}"
f"{'AI (mean +/- std)':>22}{'AI % improvement':>22}"
)
print(header)
print("-" * len(header))
for label, col_def, col_ai in metrics:
defaults = [r[col_def] for r in results]
ais = [r[col_ai] for r in results]
pct = [(d - a) / d * 100 for d, a in zip(defaults, ais)]
default_str = f"{mean(defaults):.1f} +/- {stdev(defaults):.1f}"
ai_str = f"{mean(ais):.1f} +/- {stdev(ais):.1f}"
pct_str = f"{mean(pct):+.1f}% +/- {stdev(pct):.1f}%"
print(f"{label:<12}{default_str:>24}{ai_str:>22}{pct_str:>22}")

def plot_metrics_and_pct(results, title_prefix):
"""Plot metric comparisons and percentage improvement of AI over Default."""
qubits = [r["Qubits"] for r in results]
metrics = [
("Depth 2Q (Default)", "Depth 2Q (AI)", "Two-Qubit Depth"),
("Gate Count (Default)", "Gate Count (AI)", "Gate Count"),
("Time (Default)", "Time (AI)", "Transpilation Time"),
]

# Row 1: raw metric comparison
fig, axs = plt.subplots(1, 3, figsize=(21, 5))
fig.suptitle(
f"{title_prefix}: Metric Comparison",
fontsize=15,
fontweight="bold",
y=1.02,
)
for ax, (col_def, col_ai, label) in zip(axs, metrics):
ax.plot(qubits, [r[col_def] for r in results], "o-", label="Default")
ax.plot(qubits, [r[col_ai] for r in results], "s-", label="AI")
ax.set_title(label)
ax.set_xlabel("Number of Qubits")
ax.set_ylabel(label)
ax.legend()
plt.tight_layout()
plt.show()

# Row 2: percentage improvement
fig, axs = plt.subplots(1, 3, figsize=(21, 5))
fig.suptitle(
f"{title_prefix}: % Improvement of AI over Default",
fontsize=15,
fontweight="bold",
y=1.02,
)
for ax, (col_def, col_ai, label) in zip(axs, metrics):
pct = [(r[col_def] - r[col_ai]) / r[col_def] * 100 for r in results]
ax.axhline(
0, color="#1f77b4", linewidth=2, label="Default (baseline)"
)
ax.plot(qubits, pct, "s-", color="#ff7f0e", label="AI")
ax.fill_between(qubits, 0, pct, alpha=0.15, color="#ff7f0e")
ax.set_title(label)
ax.set_xlabel("Number of Qubits")
ax.set_ylabel("% Improvement")
ax.legend()
plt.tight_layout()
plt.show()

# Suppress verbose AI-powered transpiler logs
logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.WARNING)

مثال على محاكي صغير الحجم

الخطوة 1: تعيين المدخلات الكلاسيكية إلى مسألة كمومية

نُولِّد 20 دائرة عشوائية بعمق 4، حيث يتراوح عدد البتات الكمومية من ستة إلى 25. ستكون هذه الدوائر حالات الاختبار لمقارنة استراتيجيات التحويل البرمجي.

num_circuits_sim = 20
depth_sim = 4
qubit_range_sim = list(range(6, 26))

circuits_sim = [
# We have only two qubit gates, as those test how well the transpiler can optimize the circuit.
random_circuit(
num_qubits=n,
depth=depth_sim,
max_operands=2,
num_operand_distribution={2: 1},
seed=seed + i,
)
for i, n in enumerate(qubit_range_sim)
]

print(
f"Created {len(circuits_sim)} circuits with qubit counts: {qubit_range_sim}"
)
circuits_sim[0].draw(output="mpl", fold=-1)
Created 20 circuits with qubit counts: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

مخرجات خلية الكود السابقة

الخطوة 2: تحسين المسألة للتنفيذ على أجهزة الحوسبة الكمومية

نبني مدير المسارات الافتراضي (SABRE) للواجهة الخلفية المختارة. تستهدف كلتا استراتيجيتَي التحويل البرمجي خريطة الاقتران الكاملة للواجهة الخلفية. تبقى المحاكاة المحلية لاحقًا قابلة للتنفيذ لأن خطوة المحاكاة تستخدم remap_to_contiguous لإعادة تسمية كل دائرة محوَّلة إلى بتاتها الكمومية النشطة فقط، لكي يُحاكي Aer تلك البتات الكمومية بدلًا من الجهاز بأكمله.

service = QiskitRuntimeService()
backend = service.least_busy(
min_num_qubits=100, operational=True, simulator=False
)

pm_default_sim = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
seed_transpiler=seed,
)
results_sim = []

for i, qc in enumerate(circuits_sim):
n = qubit_range_sim[i]

qc_default, m_default = transpile_with_metrics(pm_default_sim, qc)

# Create a fresh AI pass manager each iteration to avoid stale layout state
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai, m_ai = transpile_with_metrics(pm_ai, qc)

results_sim.append(
{
"Qubits": n,
"Depth 2Q (Default)": m_default["depth_2q"],
"Depth 2Q (AI)": m_ai["depth_2q"],
"Gate Count (Default)": m_default["gate_count"],
"Gate Count (AI)": m_ai["gate_count"],
"Time (Default)": m_default["time_s"],
"Time (AI)": m_ai["time_s"],
}
)

print_summary(results_sim)
Fetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]
Metric Default (mean +/- std) AI (mean +/- std) AI % improvement
--------------------------------------------------------------------------------
Depth 2Q 33.0 +/- 12.9 26.4 +/- 8.0 +15.8% +/- 17.6%
Gate Count 522.0 +/- 266.0 560.5 +/- 279.1 -9.0% +/- 9.0%
Time (s) 0.0 +/- 0.0 0.2 +/- 0.1 -893.6% +/- 362.9%

يُظهر جدول الملخص متوسط وانحراف معياري لكل مقياس عبر جميع الدوائر العشرين، إلى جانب متوسط نسبة تحسين المُحوِّل المدعوم بالذكاء الاصطناعي مقارنةً بالمُحوِّل الافتراضي. تُشير القيم الموجبة إلى أن المُحوِّل المدعوم بالذكاء الاصطناعي أعطى نتائج أفضل، بينما تُشير القيم السالبة إلى تفوق المُحوِّل الافتراضي.

في هذا المثال صغير الحجم، يُحقق المُحوِّل المدعوم بالذكاء الاصطناعي عمقًا أدنى بنحو 16% لبوابات البتتين الكموميتين في المتوسط، لكن بتكلفة زيادة بنحو 9% في عدد البوابات. يُبرز هذا مفاضلةً جوهرية عند الاختيار بين الاستراتيجيتين: يُعطي المُحوِّل المدعوم بالذكاء الاصطناعي الأولوية لتقليل العمق (طبقات أقل من بوابات البتتين الكموميتين المتسلسلة)، بينما يُعطي المُحوِّل الافتراضي (SABRE) الأولوية لتقليل إجمالي عدد البوابات (إدراج عدد أقل من بوابات SWAP). بحسب تطبيقك، قد يكون أحد هذين المقياسَين أهم من الآخر.

plot_metrics_and_pct(results_sim, "Small-Scale Random Circuits")

مخرجات خلية الكود السابقة

مخرجات خلية الكود السابقة

عمق البتتين الكموميتين: يُنتج المُحوِّل المدعوم بالذكاء الاصطناعي بوجه عام دوائر بعمق أدنى لبوابات البتتين الكموميتين. يُعدّ العمق أحد المقاييس الأساسية التي يُدرَّب نموذج التوجيه بالذكاء الاصطناعي على تحسينها، والتحسين واضح عبر معظم أحجام الدوائر، وإن كان SABRE يُضاهيه أو يتفوق عليه في دوائر بعينها.

عدد البوابات: النتائج متقاربة على هذا النطاق، مع تفوق طفيف لـ SABRE بشكل عام. صُمِّم استدلال التوجيه في SABRE لتقليل عدد بوابات SWAP المُدرجة، مما يُقلل عدد البوابات مباشرةً. عند أحجام الدوائر الصغيرة، يكون الفارق متواضعًا.

وقت التحويل البرمجي: يظل وقت تشغيل SABRE شبه ثابت بصرف النظر عن عدد البتات الكمومية، لذا يكون لحجم الدائرة تأثير محدود على وقت تحويلها البرمجي على هذا النطاق. منطق التوجيه الأساسي في SABRE مُحسَّن للغاية (مُنفَّذ إلى حد بعيد بلغة Rust). يستغرق المُحوِّل المدعوم بالذكاء الاصطناعي وقتًا أطول ويتوسع مع حجم الدائرة، وإن ظلت الأوقات الفعلية معقولةً للاستخدام التفاعلي.

الخطوة 3: التنفيذ باستخدام أوليّات Qiskit

لتقييم تأثير التحويل البرمجي على دقة الدائرة، نبني دوائر مرآتية من حالة الدائرة ذات 10 بتات كمومية وننفذها على محاكي Aer بنموذج ضوضاء بسيط. المخرج المتوقع لدائرة مرآتية هو دائمًا سلسلة البتات الصفرية، لذا فإن احتمالية قياس 0n|0\rangle^{\otimes n} تُبيِّن مدى الحفاظ على الدقة بكل استراتيجية تحويل برمجي.

# Use the 10-qubit circuit (index where qubits == 10)
idx_10q = qubit_range_sim.index(10)

qc_10q = circuits_sim[idx_10q]
qc_default_10q, _ = transpile_with_metrics(pm_default_sim, qc_10q)

pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai_10q, _ = transpile_with_metrics(pm_ai, qc_10q)

tqc_methods = {
"Default": qc_default_10q,
"AI": qc_ai_10q,
}

print(
f"Default: depth {qc_default_10q.depth()}, gates {qc_default_10q.size()}"
)
print(f"AI: depth {qc_ai_10q.depth()}, gates {qc_ai_10q.size()}")
Default: depth 84, gates 280
AI: depth 91, gates 343
# Build a simple depolarizing noise model
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(
depolarizing_error(0.001, 1),
["sx", "x", "rz"], # ~0.1% per 1Q gate
)
noise_model.add_all_qubit_quantum_error(
depolarizing_error(0.01, 2),
["cx", "ecr"], # ~1% per 2Q gate
)

aer_sim = AerSimulator(noise_model=noise_model)

shots = 10000
survival_probs = {}

for method, tqc in tqc_methods.items():
mirror = build_mirror_circuit(tqc, simulate=True)

sampler = SamplerV2(mode=aer_sim)
job = sampler.run([mirror], shots=shots)
counts = job.result()[0].data.meas.get_counts()

all_zeros = "0" * mirror.num_qubits
survival = counts.get(all_zeros, 0) / shots
survival_probs[method] = survival
print(
f"{method:8s} P(|00...0>) = {survival:.4f} ({counts.get(all_zeros, 0)}/{shots})"
)
Default P(|00...0>) = 0.8460 (8460/10000)
AI P(|00...0>) = 0.8121 (8121/10000)

شغَّلنا كلتا الدائرتَين المرآتيتَين عبر محاكي Aer مع نموذج ضوضاء depolarizing بسيط. تحدِّد احتمالية النجاة، المعرَّفة بوصفها نسبة اللقطات التي تُعيد سلسلة البتات الصفرية، مقدار الضوضاء الذي تُدخله كل استراتيجية تحويل برمجي.

الخطوة 4: المعالجة اللاحقة وإعادة النتيجة بالصيغة الكلاسيكية المطلوبة

نستخرج احتمالية قياس سلسلة البتات الصفرية من كلا التشغيلَين. تُشير احتمالية نجاة أعلى إلى دقة أفضل، أي أن التحويل البرمجي أدخل ضوضاءً أقل. يُظهر الرسم البياني أدناه المُكمِّل، أي 1 - P(|0...0>)، بحيث يُشير الشريط الأقصر إلى دقة أفضل ويُسهل رؤية الفوارق الطفيفة في الخطأ.

# Plot 1 - P(|0...0>), the probability of an erroneous (non-zero) outcome.
# A lower bar means the transpilation introduced less noise.
error_probs = {method: 1 - p for method, p in survival_probs.items()}

fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(
error_probs.keys(),
error_probs.values(),
color=["steelblue", "coral"],
)
ax.set_ylabel("1 - P(|0...0>)")
ax.set_title("Mirror Circuit Error (10-qubit, Aer Simulator)")
ax.set_ylim(0, 1)
plt.tight_layout()
plt.show()

مخرجات خلية الكود السابقة

في هذه الحالة، أنتج المُحوِّل الافتراضي دائرةً أقل عمقًا وأصغر حجمًا لهذه الحالة بالذات من 10 بتات كمومية، لذا تُعدّ دقته الأعلى متوقعة. تتباين النتائج من دائرة إلى أخرى: كما يُبيِّن جدول الملخص أعلاه، تتمثل ميزة المُحوِّل المدعوم بالذكاء الاصطناعي في انخفاض متوسط عمق البوابات ثنائية البتات الكمومية، وليس في كل دائرة بعينها. تعتمد الاستراتيجية التي تُعطي دقةً أعلى على حجم الفارق في كل مقياس وخصائص الضوضاء في الجهاز وبنية الدائرة. في ظل نموذج ضوضاء depolarizing موحد، كثيرًا ما يكون لإجمالي عدد البوابات تأثير مباشر أكبر على الخطأ المتراكم مقارنةً بالعمق وحده.

مثال على الأجهزة الحقيقية بنطاق واسع

الخطوات 1-4

هنا نجمع كل هذه التفاصيل في سير عمل واضح بنطاق أوسع، ثم ننفذه على أجهزة كمومية حقيقية.

يُولِّد الكود أدناه 25 دائرة عشوائية بعمق 8، حيث يتراوح عدد البتات الكمومية من 26 إلى 50. تُحوَّل هذه الدوائر برمجيًا باستخدام كلتا الاستراتيجيتَين وتُجمع المقاييس ذاتها. ثم نبني دوائر مرآتية من حالة الدائرة ذات 26 بتًا كموميًا ونُرسلها إلى الواجهة الخلفية الحقيقية.

# -------------------------Step 1-------------------------
num_circuits_hw = 25
depth_hw = 8
qubit_range_hw = list(range(26, 51))

circuits_hw = [
# We have only two qubit gates, as those test how well the transpiler can optimize the circuit.
random_circuit(
num_qubits=n,
depth=depth_hw,
max_operands=2,
num_operand_distribution={2: 1},
seed=seed + i,
)
for i, n in enumerate(qubit_range_hw)
]

print(
f"Created {len(circuits_hw)} circuits with qubit counts: {qubit_range_hw}"
)
Created 25 circuits with qubit counts: [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
# -------------------------Step 2-------------------------
pm_default = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
seed_transpiler=seed,
)

results_hw = []

for i, qc in enumerate(circuits_hw):
n = qubit_range_hw[i]

qc_default, m_default = transpile_with_metrics(pm_default, qc)

# Create a fresh AI pass manager each iteration to avoid stale layout state
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai, m_ai = transpile_with_metrics(pm_ai, qc)

results_hw.append(
{
"Qubits": n,
"Depth 2Q (Default)": m_default["depth_2q"],
"Depth 2Q (AI)": m_ai["depth_2q"],
"Gate Count (Default)": m_default["gate_count"],
"Gate Count (AI)": m_ai["gate_count"],
"Time (Default)": m_default["time_s"],
"Time (AI)": m_ai["time_s"],
}
)

print_summary(results_hw)
Metric Default (mean +/- std) AI (mean +/- std) AI % improvement
--------------------------------------------------------------------------------
Depth 2Q 217.4 +/- 50.4 191.0 +/- 35.6 +10.9% +/- 10.7%
Gate Count 4513.3 +/- 1394.3 5227.1 +/- 1536.4 -16.4% +/- 5.8%
Time (s) 0.1 +/- 0.0 3.5 +/- 1.5 -3588.2% +/- 643.6%
plot_metrics_and_pct(results_hw, "Large-Scale Random Circuits")

مخرجات خلية الكود السابقة

مخرجات خلية الكود السابقة

# -------------------------Step 3-------------------------
# Build mirror circuits from the 26-qubit case
idx_26q = qubit_range_hw.index(26)

qc_26q = circuits_hw[idx_26q]
qc_default_26q, _ = transpile_with_metrics(pm_default, qc_26q)

pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai_26q, _ = transpile_with_metrics(pm_ai, qc_26q)

mirror_default_hw = build_mirror_circuit(qc_default_26q, simulate=False)
mirror_ai_hw = build_mirror_circuit(qc_ai_26q, simulate=False)

# Re-transpile to basis gates (the inverse can introduce gates like sxdg)
pm_basis = generate_preset_pass_manager(
optimization_level=0,
backend=backend,
)
mirror_default_hw = pm_basis.run(mirror_default_hw)
mirror_ai_hw = pm_basis.run(mirror_ai_hw)

print(
f"Mirror circuit (Default): depth {mirror_default_hw.depth()}, gates {mirror_default_hw.size()}"
)
print(
f"Mirror circuit (AI): depth {mirror_ai_hw.depth()}, gates {mirror_ai_hw.size()}"
)

# Submit to real hardware
sampler_hw = SamplerV2(mode=backend)
sampler_hw.options.environment.job_tags = ["TUT_AITI"]

shots_hw = 500000
job_hw = sampler_hw.run([mirror_default_hw, mirror_ai_hw], shots=shots_hw)
print(f"Job submitted: {job_hw.job_id()}")
Mirror circuit (Default): depth 1577, gates 9672
Mirror circuit (AI): depth 1235, gates 11092
Job submitted: d8gt7vm6983c73dqbg0g
# -------------------------Step 4-------------------------
result_hw = job_hw.result()

survival_probs_hw = {}
for i, method in enumerate(["Default", "AI"]):
counts = result_hw[i].data.meas.get_counts()
mirror = [mirror_default_hw, mirror_ai_hw][i]
all_zeros = "0" * mirror.num_qubits
survival = counts.get(all_zeros, 0) / shots_hw
survival_probs_hw[method] = survival
print(
f"{method:8s} P(|00...0>) = {survival:.4f} ({counts.get(all_zeros, 0)}/{shots_hw})"
)

# Plot 1 - P(|0...0>), the probability of an erroneous (non-zero) outcome.
# A lower bar means the transpilation introduced less noise.
error_probs_hw = {method: 1 - p for method, p in survival_probs_hw.items()}

fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(
error_probs_hw.keys(),
error_probs_hw.values(),
color=["steelblue", "coral"],
)
ax.set_ylabel("1 - P(|0...0>)")
ax.set_title(f"Mirror Circuit Error (26-qubit, {backend.name})")
ax.set_ylim(0, 1)
plt.tight_layout()
plt.show()
Default P(|00...0>) = 0.0005 (239/500000)
AI P(|00...0>) = 0.0050 (2516/500000)

مخرجات خلية الكود السابقة

تحليل النتائج

تُؤكد نتائج النطاق الواسع الاتجاهات التي لوحظت في المثال صغير الحجم، لكن على نطاق أكثر تطلبًا.

عمق البتتين الكموميتين: يواصل المُحوِّل المدعوم بالذكاء الاصطناعي تقديم عمق أدنى بشكل ملحوظ لبوابات البتتين الكموميتين عبر النطاق الكامل لأحجام الدوائر. يُعدّ تحسين العمق أحد الأهداف الأساسية التي يُدرَّب عليها نموذج التوجيه بالذكاء الاصطناعي، والميزة أكثر وضوحًا عند عدد أكبر من البتات الكمومية حيث تزداد صعوبة مسألة التوجيه على الأساليب الاستدلالية.

عدد البوابات: يُنتج المُحوِّل الافتراضي (SABRE) باستمرار دوائر بعدد أقل من البوابات عبر جميع أحجام الدوائر في هذا النطاق. صُمِّم استدلال SABRE تحديدًا لتقليل عدد البوابات، وعلى هذا النطاق تكون الميزة واضحة وموحدة.

وقت التحويل البرمجي: يتسع الفارق في وقت التحويل البرمجي على نطاقات أكبر. يظل SABRE شبه ثابت، بينما يتصاعد وقت تشغيل المُحوِّل المدعوم بالذكاء الاصطناعي بشكل أحدّ. رغم ذلك، يظل وقت تشغيل المُحوِّل المدعوم بالذكاء الاصطناعي عمليًا لمعظم سير العمل.

دقة الدائرة المرآتية: تُنتج كلتا الطريقتَين احتمالية نجاة تقل بكثير عن 1% على هذا النطاق، مما يُبقي الإشارة المفيدة ضئيلة. مع إجماليات عدد البوابات حول 10,000 وأعماق البوابات ثنائية البتات الكمومية التي تتجاوز 1,000، تطغى ضوضاء الاستقطاب المتراكمة عبر الدائرة المرآتية على معظم الإشارة. يُبرز هذا قيودًا جوهرية لأسلوب الدائرة المرآتية: رغم بساطته وعدم حاجته إلى محاكاة كلاسيكية، لا يتوسع جيدًا مع الدوائر الكبيرة أو العميقة، حيث يُدفع الأسلوبان نحو مستوى الضوضاء وتُهيمن الأخطاء المتراكمة على الإشارة الضئيلة الباقية.

بينما تُؤكد هذه النتائج فعالية المُحوِّل المدعوم بالذكاء الاصطناعي، من المهم ملاحظة قيوده. أسلوب التوليف بالذكاء الاصطناعي متاح حاليًا فقط لخرائط اقتران معينة، مما قد يُقيِّد تطبيقه على نطاق أوسع. ينبغي مراعاة هذا القيد عند تقييم استخدامه في سيناريوهات مختلفة.

الخطوات التالية

توصيات

إذا وجدت هذا العمل مثيرًا للاهتمام، فقد تهمك المواد التالية: