מעבר מ-NoiseLearner ל-NoiseLearnerV3
מדריך זה ילווה אותך במעבר מ-IBM Quantum® NoiseLearner ל-NoiseLearnerV3. שתי
המחלקות מבצעות ניסויים שמאפיינים תהליכי רעש בהתבסס על
מודל רעש Pauli-Lindblad, אך הקלטים
והפלטים שונים במעט.
רקע
המחלקה NoiseLearner
נוצרה כדי לאפשר למשתמשים לבצע למידת רעש מפורשת. את מודל הרעש
המתקבל ניתן אז להעביר ל-Estimator של IBM Quantum כדי להחיל טכניקות הפחתת שגיאות
כגון PEA ו-PEC.
NoiseLearner תוכנן לעבוד עם Estimator, ולכן הוא מפעיל באופן מרומז את אותה
אסטרטגיית מציאת שכבות כמו Estimator. לא ניתן לשנות אסטרטגיה זו; אחרת, שלבי
ההפחתה הבאים לא יעבדו כראוי.
החל מ-qiskit-ibm-runtime v0.47.0, יש מחלקה חדשה
NoiseLearnerV3
שתואמת ל-primitive Executor ול-
מודל הביצוע המכוון.
המודל החדש הזה מספק חוויית קופסה שקופה על ידי מתן הרכיבים ללכידת כוונת העיצוב
בצד הלקוח, ו-primitive יחיד בצד השרת (Executor) מעבד את הקלטים האלה בדיוק כפי
שהונחה — הוא אינו מקבל החלטות מרומזות מטעמך. בניגוד ל-NoiseLearner המקורי,
אתה שולט כיצד לחלק את המעגלים שלך לשכבות כאשר אתה משתמש ב-NoiseLearnerV3, והמחלקה פשוט מקבלת רשימה של הוראות מעגל ממוסגרות
(לדוגמה, שכבות ייחודיות) כקלט שלה.
NoiseLearnerV3 גם תומך בלמידת רעש מדידה. עבור כל הוראה ברשימת הקלט, הוא מריץ את
פרוטוקול הלמידה Pauli-Lindblad אם הקופסה מכילה שערים של קיובט אחד ושני קיובטים, ואת פרוטוקול
TREX
אם הקופסה מכילה מדידות.
האם כדאי לך לעבור?
NoiseLearner עובד רק עם ה-Estimator הישן בצד השרת, ו-NoiseLearnerV3 עובד רק עם
Executor וה-Estimator בצד הלקוח. עליך לעבור ל-NoiseLearnerV3 אם אתה משתמש
ב-Executor או ב-Estimator בצד הלקוח. ה-Estimator הישן בצד השרת הוצא משימוש והוחלף במקבילה בצד הלקוח ב-qiskit-ibm-runtime v0.50.0.
אם אתה משתמש ב-qiskit-ibm-runtime v0.50.0 או גרסה מאוחרת יותר, קרא את המדריך מעבר מ-Sampler ו-Estimator בצד השרת לצד הלקוח כדי לעבור תחילה ל-primitives בצד הלקוח.
שלבי מעבר
שלב 1: שנה את ה-imports
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
NoiseLearnerV3:
from qiskit_ibm_runtime import NoiseLearnerV3
שלב 2: עדכן את הקלטים
השיטה run() של NoiseLearner מקבלת רשימה של מעגלים או PUBs, בעוד שהשיטה run() של NoiseLearnerV3 מקבלת רשימה של הוראות, שכל אחת מהן חייבת להיות BoxOp עם הערת twirling שמכילה פעולות ISA.
שיטות נוחות זמינות ליצירת הקופסאות המוערות, בהתאם ל-
primitive שבו אתה מתכנן להשתמש.
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
learner = NoiseLearner(mode=backend)
# `circuits_to_learn` is a list of ISA QuantumCircuit
learner_job = learner.run(circuits_to_learn)
NoiseLearnerV3, כאשר עובדים עם Estimator בצד הלקוח:
אם אתה מתכנן להשתמש ב-Estimator בצד הלקוח לביצוע מעגלים, אתה יכול להשתמש בשיטה find_unique_layers מ-Estimator כדי ליצור קופסאות מוערות (שכבות):
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
pubs = [...] # Your PUBs
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Learn the noise model for those layers (runs as a separate job).
learner = NoiseLearnerV3(backend)
learner_job = learner.run(layers)
NoiseLearnerV3, כאשר עובדים עם Executor:
אם אתה מתכנן להשתמש ב-Executor לביצוע מעגלים, שקול להשתמש בפונקציה generate_boxing_pass_manager מ-Samplomatic כדי ליצור קופסאות מוערות:
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# Run the boxing pass manager to group instructions into annotated boxes.
# `isa_circuit` is an ISA QuantumCircuit.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# Find unique boxed instructions.
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program.
learner = NoiseLearnerV3(backend)
learner_job = learner.run(unique_box_instructions)
שלב 3: המר את האפשרויות
רוב השדות של NoiseLearnerOptions ממופים ישירות ל-NoiseLearnerV3Options, למעט הבאים:
-
max_layers_to_learn: עםNoiseLearnerV3, מספר השכבות שיש ללמוד מבוסס על מספר השכבות שהועברו. -
twirling_strategy: עםNoiseLearnerV3, אסטרטגיית ה-twirling מוגדרת על ידי האופן שבו ההוראות ממוסגרות ומוערות (כגון בעת שימוש ב-generate_boxing_pass_manager()).
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
from qiskit_ibm_runtime.options import NoiseLearnerOptions
# Instantiate a NoiseLearnerOptions object
learner_options = NoiseLearnerOptions(
max_layers_to_learn=3, num_randomizations=32, twirling_strategy="all"
)
learner = NoiseLearner(mode=backend, options=learner_options)
learner_job = learner.run(circuits_to_learn)
NoiseLearnerV3, כאשר עובדים עם Estimator בצד הלקוח:
אם אתה מתכנן להשתמש ב-Estimator בצד הלקוח לביצוע מעגלים, אתה יכול
להגדיר את אפשרות ה-Estimator twirling.strategy:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
from qiskit_ibm_runtime.options_models import NoiseLearnerV3Options
pubs = [...] # Your PUBs
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
estimator.options.twirling.strategy = "all" # set twirling strategy here
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program
learner_options = NoiseLearnerV3Options(num_randomizations=32)
learner = NoiseLearnerV3(backend, options=learner_options)
# Learn just the first 3 layers.
learner_job = learner.run(layers[:3])
NoiseLearnerV3, כאשר עובדים עם Executor:
אם אתה מתכנן להשתמש ב-Executor לביצוע מעגלים, אתה יכול להעביר את האפשרות twirling_strategy לפונקציה generate_boxing_pass_manager.
שים לב שעם generate_boxing_pass_manager(), ערכי ה-twirling_strategy משתמשים בקווים תחתונים
("active_accum", "active_circuit"), בעוד ש-NoiseLearnerOptions.twirling_strategy משתמש במקפים ("active-accum", "active-circuit").
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
from qiskit_ibm_runtime.options_models import NoiseLearnerV3Options
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# Run the boxing pass manager to group instructions into annotated boxes
# `isa_circuit` is an ISA QuantumCircuit
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
twirling_strategy="all", # twirling strategy can be specified here
inject_noise_targets="gates",
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# Find unique boxed instructions
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
learner_options = NoiseLearnerV3Options(num_randomizations=32)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program
learner = NoiseLearnerV3(backend, options=learner_options)
# Learn just the first 3 layers.
learner_job = learner.run(unique_box_instructions[:3])
שלב 4: בדוק את התוצאות
הפלטים של NoiseLearner ו-NoiseLearnerV3 מכילים מידע דומה אך בתבניות שונות. עדכן את הקוד שלך אם הוא בודק את הפלט באופן מפורש.
מיפוי תכונות תוצאה:
(learner_result הוא הפלט של job הלמידה)
| תכונה | NoiseLearner | NoiseLearnerV3 |
|---|---|---|
| סוג התוצאה | NoiseLearnerResult | NoiseLearnerV3Results, מכולה דמוית-רצף של NoiseLearnerV3Result |
| מספר השכבות שנלמדו | len(learner_result.data) | len(learner_result) |
| נתונים עבור השכבה הראשונה | layer_error = learner_result.data[0] | noise_map = learner_result[0].to_pauli_lindblad_map() |
| סוג התוצאה של כל שכבה | LayerError (type(layer_error)) | PauliLindbladMap (type(noise_map)) |
| גנרטורים לערוץ השגיאה | layer_error.error.generators | noise_map.generators() |
| שיעורי שגיאה | layer_error.error.rates | noise_map.rates |
שלב 5: הזנת מודל רעש ל-primitive
NoiseLearner עובד רק עם ה-Estimator הישן בצד השרת, ו-NoiseLearnerV3 עובד רק עם Executor וה-Estimator בצד הלקוח. האופן שבו מודל רעש מצוין משתנה מעט בהתאם ל-primitive שבו נעשה שימוש.
NoiseLearner, כאשר עובדים עם Estimator הישן בצד השרת:
from qiskit_ibm_runtime import Estimator as LegacyEstimator
learner_result = learner_job.result()
# Pass the noise model to the `estimator.options` attribute directly
estimator = LegacyEstimator(mode=backend)
estimator.options.resilience.layer_noise_model = learner_result
job = estimator.run(pubs)
NoiseLearnerV3, כאשר עובדים עם Estimator בצד הלקוח:
השתמש שוב באותו Estimator שהפיק את layers בשלב 2. מפות הרעש שהוחזרו על ידי
הלומד מותאמות מיקומית לשכבות אלה, ולכן יש להקצות אותן ל-Estimator
ממנו הן הגיעו. PEA/PEC כבר היה מופעל עליו בשלב 2.
שים לב שבעוד ש-NoiseLearnerV3 תומך גם בפרוטוקול Pauli-Lindblad וגם בפרוטוקול TREX, Estimator מקבל רק מודלי רעש עבור שכבות דו-קיובטיות שנלמדו עם פרוטוקול Pauli-Lindblad.
learner_result = learner_job.result()
# Convert results to Pauli-Lindblad noise maps.
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
# Assign the learned noise maps so PEA/PEC uses them.
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# Now execute the target PUBs.
job = estimator.run(pubs)
NoiseLearnerV3, כאשר עובדים עם Executor:
from qiskit_ibm_runtime import Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
# Generate a quantum program
program = QuantumProgram(shots=1000)
# Convert the NoiseLearnerV3 result to a dictionary
learner_result = learner_job.result()
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)
# Append the samplex item and execute
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"pauli_lindblad_maps": noise_maps,
},
)
executor = Executor(backend)
executor_job = executor.run(program)
דוגמאות מלאות
NoiseLearnerV3 ו-Estimator בצד הלקוח
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, NoiseLearnerV3
from qiskit_ibm_runtime.executor_estimator import Estimator
# 1. Account + backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit + observable
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
observable = SparsePauliOp("ZZ")
# 3. Transpile to ISA
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
pubs = [(isa_circuit, isa_observable)]
# 4. Initialize Estimator with options
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True
# 5. Extract the unique boxed layers from PUBs
layers = estimator.find_unique_layers(pubs)
# 6. Learn the noise model for those layers
learner = NoiseLearnerV3(backend)
learner_job = learner.run(layers)
learner_result = learner_job.result()
# 7. Convert the result to Pauli-Lindblad maps and pass them to Estimator
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# 8. Execute the target PUBs
job = estimator.run(pubs)
result = job.result()
NoiseLearnerV3 ו-Executor
from qiskit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Executor, NoiseLearnerV3
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# 1. Account + backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit + observable
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# 3. Transpile to ISA
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
# 4. Run the boxing pass manager to group instructions into annotated boxes
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# 5. Find unique boxed instructions (layers)
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
# 6. Learn the noise model for those layers
learner = NoiseLearnerV3(backend)
learner_job = learner.run(unique_box_instructions)
learner_result = learner_job.result()
# 7. Convert the NoiseLearnerV3 result to a dictionary
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)
# 8. Build the template circuit and samplex pair
template_circuit, samplex = build(boxed_circuit)
# 9. Prepare a quantum program
program = QuantumProgram(shots=1000)
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"pauli_lindblad_maps": noise_maps,
},
)
executor = Executor(backend)
job = executor.run(program)
result = job.result()