דלג לתוכן הראשי
פרויקט זה בשלב בטא. מצאת באג? פתח issue ב-GitHub. יש שאלה או רעיון? שאל ב-Discussions — נשמח לשמוע ממך!
מה איכות התרגום בדף זה?

למידת מודל הרעש של שער

המדריך הזה מדגים למידה של מודל רעש לשער יוניטרי באמצעות פרוטוקול למידה סטנדרטי, הזמין דרך פונקציות הפרוטוקול ברמה גבוהה prepare_vanilla_program() ו-process_vanilla_result().

  1. הגדרת השער

  2. הגדרת סימולציה מקומית

  3. הכנת התוכנית הקוונטית

  4. הרצת התוכנית הקוונטית

  5. קריאת התוצאות

הרצה על חומרה אמיתית

המעגלים שלמטה מסומלצים מקומית, ולכן המדריך הזה לא דורש פרטי גישה של IBM Quantum®. כדי להריץ אותו במקום זה על מכשיר אמיתי:

  • שלב 1: מחליפים את FakeMarrakesh ב-Backend אמיתי.

  • שלב 2: מעבירים את ה-Backend הזה בתור ה-mode של ה-executor, ומסירים את אפשרויות הסימולטור.

1. הגדרת השער​

השער הוא BoxOp שמכיל שכבה עם twirling של שישה שערי CZ זרים.

from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from samplomatic import InjectNoise, Tag, Twirl

backend = FakeMarrakesh()

cz_pairs = [(91, 92), (93, 94), (95, 99), (98, 111), (112, 113), (114, 115)]

circuit = QuantumCircuit(backend.num_qubits)
with circuit.box([Twirl(), Tag("cz_gate"), InjectNoise("cz_gate")]):
for pair in cz_pairs:
circuit.cz(*pair)
הרצה על חומרה אמיתית
from qiskit_ibm_runtime import QiskitRuntimeService

backend = QiskitRuntimeService().backend("ibm_marrakesh")

2. הגדרת סימולציה מקומית​

אינדקסי הפאולי בכל מפה הם מקומיים לשער, לפי סדר עולה של ה-Qubit הפיזי:

cz_qubits = sorted({qubit for pair in cz_pairs for qubit in pair})
local = {qubit: index for index, qubit in enumerate(cz_qubits)}
local
{91: 0,
92: 1,
93: 2,
94: 3,
95: 4,
98: 5,
99: 6,
111: 7,
112: 8,
113: 9,
114: 10,
115: 11}

מגדירים את הרעש עם איבר ZZ מתואם ואיבר XX חלש יותר על כל זוג CZ, ובנוסף איבר Z של Qubit בודד בכל מקום; למדידה יש איבר היפוך סיביות לכל Qubit.

from qiskit.quantum_info import PauliLindbladMap

num_qubits = len(cz_qubits)

cz_noise = PauliLindbladMap.from_sparse_list(
[("ZZ", [local[a], local[b]], 8e-4) for a, b in cz_pairs]
+ [("XX", [local[a], local[b]], 4e-4) for a, b in cz_pairs]
+ [("Z", [index], 3e-4) for index in range(num_qubits)],
num_qubits=num_qubits,
)

readout_noise = PauliLindbladMap.from_sparse_list(
[("X", [index], 5e-3) for index in range(num_qubits)], num_qubits=num_qubits
)

בונים קופסה שהמדידה תלמד.

measurement = QuantumCircuit(backend.num_qubits, num_qubits)
with measurement.box([Twirl(), Tag("readout"), InjectNoise("readout")]):
for clbit, qubit in enumerate(cz_qubits):
measurement.measure(qubit, clbit)

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

from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import Executor

executor = Executor(
mode=AerSimulator(method="stabilizer"),
options={
"simulator": {
"layer_noise_model": [
(circuit[0], cz_noise),
(measurement[0], readout_noise),
],
"seed_simulator": 1234,
}
},
)
הרצה על חומרה אמיתית
executor = Executor(mode=backend)

3. הכנת התוכנית הקוואנטית​

משתמשים ב-prepare_vanilla_program() כדי לבנות את התוכנית הקוואנטית שמכילה את ניסויי הלמידה.

from qiskit_noise_learning.protocols import prepare_vanilla_program

program = prepare_vanilla_program(
backend,
[circuit[0], measurement[0]],
fragment_depths=[2, 16, 64, 128],
num_randomizations=50,
shots_per_randomization=20,
)

print(f"Number of template circuits: {len(program.items)}")
Number of template circuits: 5

4. הרצת התוכנית הקוואנטית​

שולחים את התוכנית הקוואנטית. השלב הזה זהה בין אם ה-executor מכוון לסימולטור ובין אם להתקן אמיתי.

result = executor.run(program).result()

5. קריאת התוצאות​

מעבדים את התוצאה באמצעות process_vanilla_result().

from qiskit_noise_learning.protocols import process_vanilla_result

noise_maps, gate_names, fit = process_vanilla_result(result)

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

fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)