Runtime yürütmesi — primitives, PUB ve hedef-bağımsız hesap
Qiskit Runtime; backend.run(...)'un üstüne kurulmuş, "devreyi gönder, sayım gel" boyutunu aşan yeni bir yürütme katmanıdır. Tek bir devre koşmak yerine, primitives denilen yardımcılar (Sampler, Estimator) algoritmanın istediği çıktının kendisini hedefler: ölçüm dağılımı, beklenen değer, varyans. Çağrı arayüzü PUB (Primitive Unified Bloc) hâline gelmiştir; aynı kod yerel Aer'de, FakeBackend'de, bir Session içinde veya gerçek IBM donanımında değişmeden çalışır. Bu sayfa primitives'i kavramsal olarak anlatır, PUB biçimini açar, mode parametresi üzerinden bağlam seçimini gösterir, hata azaltma ve opsiyon yüzeyine değinir; tüm çalışan örnekler yereldir (hesap/token gerektirmez).
Primitives nedir, ne çözer?
Primitives, Qiskit'in algoritma yazarına sunduğu üst düzey yürütme arayüzleridir. Geleneksel backend.run(...) dünyasında kullanıcı; transpile, shot, ölçüm okuma ve istatistik adımlarını elle koreografi ederdi. Primitives bunu tek soruda toplar: "bana ölçüm dağılımı ver" (Sampler) ve "bana beklenen değer ver" (Estimator). Algoritma kodu, hedefin simülatör veya gerçek donanım olduğundan habersiz yazılabilir; primitives seçilen modda işi yürütür, sonucu döndürür.
Neden ayrı bir katman?
Bir devreyi koşmanın "doğru yolu" bağlama göre değişir: yerel simülatör için shot bile gereksizken, gerçek donanımda hata azaltma ve okuma düzeltmesi kritik olabilir. Bu kararları algoritma sayfasından koparmak için primitives bir sözleşme arayüzü sunar; alt katmanın detayını saklar ve algoritmanın yalnızca çıktı talebine odaklanmasını sağlar.
Bu sayfanın sınırı
Bu sayfa primitives'in çekirdek kullanımına odaklanır; oturum disiplinleri session mantığı sayfasında, asenkron tutamağı job sistemi sayfasında derinleştirildi. Burada amaç Sampler ve Estimator'ın davranışını ve PUB biçimini netleştirmektir.
V1'den V2'ye: PUB tabanlı çağrı
Eski V1 primitives'inde her çağrı belirli pozisyonel argümanlarla yapılırdı
(sampler.run(circuits, parameter_values=...)). V2
tarafında çağrılar PUB birimleri üzerinden ifade edilir:
Sampler için bir PUB tipik olarak (circuit, parameter_values?,
shots?); Estimator için (circuit, observables,
parameter_values?) dizisidir. Tek bir çağrıda farklı yapıdaki PUB'lar bir
liste hâlinde verilebilir; karşılığında her PUB için ayrı bir sonuç döner.
Bu tasarım, hem batch hem tek çağrı kalıbını tek arayüzde toplar.
Aynı kod, farklı hedef
SamplerV2 ve EstimatorV2 mode parametresiyle kurulur (aşağıda detay). PUB biçimi mode'dan bağımsız aynı kalır; yani algoritmik kod yerelden buluta taşınırken yeniden yazılmaz, yalnızca ortam parametresi değişir. Bu da Qiskit Runtime'ın temel vaadidir.
Doğrudan import ipucu
Yereldeki örnekler için qiskit_ibm_runtime paketindeki
sınıfları yerel FakeBackend veya Aer ile birlikte kullanmak yeterlidir; gerçek
servise (QiskitRuntimeService) ihtiyaç yoktur.
Sampler ile ölçüm dağılımı
Sampler, klasik ölçüm sonucu içeren bir devreyi alır ve karşılığında bit dizgi dağılımı verir. V2 sonuç yapısı, her PUB için bir öğe içeren bir liste döndürür; her öğenin .data alanı, devredeki klasik kayıtların adıyla erişilebilen alt nesnelere sahiptir (örneğin result[0].data.c.get_counts() ya da result[0].data.meas.get_counts()). Sampler, ölçümlü devre tasarımının doğal sonuca taşıyıcısıdır.
Klasik kayıt adının önemi
qc.measure_all() klasik kayıt adını meas yapar; qc.measure([0, 1], [0, 1]) ise varsayılan c adıyla bir kayıt oluşturur. Sampler sonucundan veri çekerken bu adın doğru bilinmesi gerekir; kod boyunca tutarlı kullanmak okunabilirliği artırır.
Shot ve bütçe
sampler.run([(qc,)], shots=...) ile shot sayısı çağrı başına verilebilir. Yerelde shot ölçeği doğrudan süreye yansır; shot mantığı sayfası bu seçimin istatistik tarafını derinleştirir.
Estimator ile beklenen değer
Estimator, devre + gözlemlenebilir (observable) çiftini alır ve doğrudan ⟨ψ|O|ψ⟩ değerini hesaplar. Algoritma yazarı, bit dizgi sayımlarını elle Pauli beklentilerine çevirmekten kurtulur; gözlemlenebilir bir SparsePauliOp veya PauliList olarak ifade edilir. Bu, VQE / QAOA gibi varyasyonel algoritmaların doğal arayüzüdür.
Ölçüm yok, gözlemlenebilir var
Estimator için devre ölçümsüz verilir; ölçüm tabanını gözlemlenebilir belirler. Bu, "aynı devreyi farklı operatörler için farklı bazlarda okuyabilirim" disiplinine doğrudan eşler.
SparsePauliOp ile ifade
SparsePauliOp.from_list([("ZZ", 1.0), ("XX", -0.5)])
gibi bir ifade, 2 qubit'lik bir Hamiltoniyen'i kısa formda verir. Estimator, bu operatör
için ortalama değeri tek çağrıda döndürür; iterasyonel optimizatörler bu sayıyı doğrudan
kayıp/değer fonksiyonu olarak kullanır.
Mode parametresi: backend, session, batch
Primitives nesnesi kurulurken alınan mode argümanı üç farklı bağlam üretir: doğrudan bir backend verilirse çağrılar ad-hoc yapılır, bir Session verilirse aynı oturum içinde paketlenir, bir Batch verilirse art arda gönderim tek pakette gruplanır. Algoritmik kod aynı kalır; mod seçimi kuyruk ve maliyet açısından farklı sonuçlar üretir. Karar disiplinini session mantığı ve kuyruk mantığı sayfaları ile birleşik okumak gerekir.
Yerel mod: backend = FakeBackend / Aer
Yerelde primitives, doğrudan bir FakeBackend veya Aer örneğini mode olarak alır. Bu, ağa çıkmadan tüm akışı denemenizi mümkün kılar. Aer simülatörü ve fake backend sayfaları bu hedeflerin niteliklerini tartışır.
Hibrit kullanım
Bir session içinde batch işler dönmek mümkündür: optimizatör her iterasyonda bir batch paketi gönderir, sonuçlar session'a düşer. Bu hibrit kalıp, üretim akışlarının normal örüntüsüdür; algoritma sayfası bu kararı bilmek zorunda değildir.
Seçenekler ve hata azaltma çengelleri
Primitives kurulumunda options alanı, optimizasyon düzeyi, dynamical decoupling, ölçüm hata düzeltmesi, twirling ve zero-noise extrapolation gibi pek çok hata azaltma ayarına çengel sağlar. Bu seçenekler bağlamdan bağlama anlamlıdır: ideal Aer'da çoğunlukla gereksizdir; FakeBackend'in gürültü modelinde etkisini görmeye başlarsınız; gerçek donanımda raporlanan rakamları belirgin biçimde değiştirebilir.
Yerelde gözlemlenebilirlik
Yerel hedeflerde bile seçeneklerin etkisini ölçmek mantıklıdır: aynı PUB'ı seçeneksiz ve seçenekli kurup karşılaştırmak, hata azaltma adımlarının nasıl davrandığını anlamanın kolay yoludur. Hata azaltma fikri sayfası, kuramsal arka planı sağlar.
Sürüm dikkati
Seçenek isimleri ve varsayılanları sürüme göre değişebilir; üretim koduna geçerken doğrudan resmi belgeye bakmak ve doğrulanmış bir varsayılan listesi tutmak iyi bir alışkanlıktır.
Result yapısı ve çoklu PUB
V2 result yapısı, çağrıya verilen PUB listesiyle birebir hizalı bir liste döndürür. Sampler için her öğe .data ile ölçüm verisine, Estimator için .data.evs (expectation values) ve .data.stds (standart sapmalar) alanlarına erişim verir. Bu sözleşme; tek devre, çok devre, çok parametre ve çok observable senaryolarını aynı kabuk altında düşünmeyi mümkün kılar.
Çoklu PUB tek çağrı
Aynı kuyruğa yapılacak ardışık gönderimleri tek çağrıda göndermek (her biri ayrı PUB), kuyruk maliyetini büyük ölçüde düşürür. Bu yaklaşım kuyruk mantığı sayfasında ele alınan "az ve büyük gönderim" disiplinini destekler.
Endian, klasik kayıt adı
Sampler verisini okurken devredeki klasik kayıt adını ve Qiskit'in endian (sağdan-sola) okuma sözleşmesini hatırlamak gerekir; raporda farklı bir kütüphane ile karşılaştırma yapacaksanız endian'ı açıkça yazın.
backend.run'dan primitives'e geçiş
backend.run(...) hâlâ yaşıyor ve eğitim için son derece uygun; ancak üretimde primitives, hem hedef-bağımsızlık hem hata azaltma çengelleri açısından kazanç sağlar. Geçişin pratik adımları: (1) algoritmanın "ne istediğini" netleştirin — dağılım mı, beklenen değer mi? (2) çağrıyı PUB hâline getirin. (3) primitives nesnesini ortam mode'una göre kurun. (4) sonuç okuma kodunu V2'nin .data alanlarına uyarlayın.
Geriye dönük uyum
backend.run(...).result().get_counts() kalıbı kısa devre ve hızlı prototip için hâlâ değerlidir; primitives ile yarışmaz, onun altında çalışan farklı bir patikadır. Aynı projede iki yolu birlikte kullanmak iyi düşünülmüş tasarım için doğaldır.
Test stratejisi
Aynı algoritmayı önce ideal Aer'da, sonra gürültülü FakeBackend'de, sonra (varsa) gerçek donanımda koşturmak; primitives'in bağlam-değiştirme vaadinin sınanmasıdır. Bu üç adımı bir test akışı olarak otomatikleştirmek üretim disiplinine yakışır.
Kod laboratuvarı
Üç blok da tamamen yereldir: ağ yok, IBM hesabı yok. Birinci blok SamplerV2'yi FakeBackend üzerinde PUB ile gösterir; ikinci blok EstimatorV2 ile beklenen değer hesabını paylaşır; üçüncü blok tek çağrıda çoklu PUB göndererek iki farklı parametre setini batch gibi paketler.
# from qiskit_ibm_runtime import QiskitRuntimeService, Session, SamplerV2, EstimatorV2
# service = QiskitRuntimeService()
# backend = service.least_busy(simulator=False, operational=True)
# with Session(backend=backend) as session:
# sampler = SamplerV2(mode=session)
# estimator = EstimatorV2(mode=session)
# dist = sampler.run([(qc_meas,)]).result()
# evs = estimator.run([(qc_state, observable)]).result()
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all() # klasik kayıt adı: 'meas'
backend = FakeManilaV2()
sampler = Sampler(mode=backend)
# PUB: (circuit,) yeterli; PUB tek elemanlıdır.
job = sampler.run([(qc,)], shots=1024)
result = job.result()
# Result yapısı: her PUB için bir öğe; .data altında klasik kayıt adı
counts = result[0].data.meas.get_counts()
print("counts:", counts)
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
# Estimator için devre ölçümsüz verilir
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
H = SparsePauliOp.from_list([("ZZ", 1.0), ("XX", -0.5)])
backend = FakeManilaV2()
estimator = Estimator(mode=backend)
# PUB: (circuit, observable[, params])
job = estimator.run([(qc, H)])
result = job.result()
print("<ψ|H|ψ> =", float(result[0].data.evs))
if hasattr(result[0].data, "stds"):
print("std =", float(result[0].data.stds))
import numpy as np
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
theta = Parameter("theta")
qc = QuantumCircuit(2)
qc.h(0)
qc.rz(theta, 0)
qc.cx(0, 1)
H = SparsePauliOp.from_list([("ZZ", 1.0)])
backend = FakeManilaV2()
estimator = Estimator(mode=backend)
# Çoklu PUB tek çağrı: her PUB ayrı parametre vektörü
pubs = [
(qc, H, [0.0]),
(qc, H, [np.pi / 2]),
(qc, H, [np.pi]),
]
result = estimator.run(pubs).result()
for (_, _, params), out in zip(pubs, result):
print(f"theta={params[0]:5.2f} ⟨ZZ⟩={float(out.data.evs):+.3f}")
İleri okuma ve özet
Runtime yürütmesi, "devreyi koş ve sayım al"dan "algoritmanın istediği çıktıyı üret"e geçen üst düzey katmandır. Sampler dağılım, Estimator beklenen değer verir; çağrı PUB biçimindedir; mode parametresi yerel, session, batch arasında geçişi tek noktada tutar. Yerelde aynı kodu kurarak buluta sorunsuz taşınırsınız.
- Backend mimarisi — BackendV2 sözleşmesi.
- Provider sistemi — kimlik ve katalog.
- Session mantığı ve kuyruk mantığı — iteratif iş yükleri.
- Job sistemi — asenkron tutamak.
- Fake backend kullanımı ve Aer simülatörü — yerel öğretim hedefleri.
- Hata azaltma fikri — seçenek arka planı.