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

الترحيل من NoiseLearner إلى NoiseLearnerV3

يرشدك هذا الدليل خلال عملية الترحيل من NoiseLearner الخاص بـ IBM Quantum® إلى 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 القديم من جانب الخادم مهملاً (deprecated) واستُبدل بالمكافئ من جانب العميل في qiskit-ibm-runtime الإصدار v0.50.0.

ملاحظة

إذا كنت تستخدم qiskit-ibm-runtime الإصدار v0.50.0 أو أحدث، فاقرأ دليل الترحيل من Sampler وEstimator من جانب الخادم إلى جانب العميل للترحيل إلى primitives من جانب العميل أولاً.

خطوات الترحيل​

الخطوة 1: تغيير عمليات الاستيراد​

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 هي مخرجات مهمة التعلم)

السمةNoiseLearnerNoiseLearnerV3
نوع النتيجةNoiseLearnerResultNoiseLearnerV3Results، حاوية شبيهة بالتسلسل (sequence-like) من 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()

المراجع​