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

מעבר מ-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 הלמידה)

תכונהNoiseLearnerNoiseLearnerV3
סוג התוצאהNoiseLearnerResultNoiseLearnerV3Results, מכולה דמוית-רצף של 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.generatorsnoise_map.generators()
שיעורי שגיאהlayer_error.error.ratesnoise_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()

מקורות​