Lewati ke konten utama

Simulasi eksak dengan primitif Qiskit SDK

Versi paket

Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami menyarankan menggunakan versi ini atau yang lebih baru.

qiskit[all]~=2.3.0

Primitif referensi di Qiskit SDK melakukan simulasi statevector lokal. Simulasi ini tidak mendukung pemodelan noise perangkat, tetapi berguna untuk membuat prototipe algoritma dengan cepat sebelum melihat teknik simulasi yang lebih canggih (menggunakan Qiskit Aer) atau menjalankan pada perangkat nyata (Qiskit Runtime primitives).

Primitif Estimator dapat menghitung nilai ekspektasi dari Circuit, dan primitif Sampler dapat mengambil sampel dari distribusi output Circuit.

Bagian berikut menunjukkan cara menggunakan primitif referensi untuk menjalankan alur kerjamu secara lokal.

Gunakan Estimator referensi​

Implementasi referensi dari EstimatorV2 di qiskit.primitives yang berjalan pada simulator statevector lokal adalah kelas StatevectorEstimator. Ia dapat menerima Circuit, observable, dan parameter sebagai input dan mengembalikan nilai ekspektasi yang dihitung secara lokal.

Kode berikut mempersiapkan input yang akan digunakan dalam contoh-contoh berikutnya. Tipe input yang diharapkan untuk observable adalah qiskit.quantum_info.SparsePauliOp. Perhatikan bahwa Circuit dalam contoh ini bersifat parametrized, tetapi kamu juga bisa menjalankan Estimator pada Circuit yang tidak diparametrasi.

catatan

Setiap Circuit yang diteruskan ke Estimator tidak boleh menyertakan pengukuran apa pun.

# Added by doQumentation β€” required packages for this notebook
!pip install -q numpy qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

# circuit for which you want to obtain the expected value
circuit = QuantumCircuit(2)
circuit.ry(Parameter("theta"), 0)
circuit.h(0)
circuit.cx(0, 1)
circuit.draw("mpl", style="iqp")

Output of the previous code cell

from qiskit.quantum_info import SparsePauliOp
import numpy as np

# observable(s) whose expected values you want to compute

observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1])

# value(s) for the circuit parameter(s)
parameter_values = [[0], [np.pi / 6], [np.pi / 2]]
Transpile ke ISA circuits dan observable

Alur kerja primitif Qiskit Runtime memerlukan Circuit dan observable untuk diubah agar hanya menggunakan instruksi yang didukung oleh QPU (disebut sebagai instruction set architecture (ISA) Circuit dan observable). Primitif referensi masih menerima instruksi abstrak, karena mereka mengandalkan simulasi statevector lokal, tetapi men-transpile Circuit mungkin tetap bermanfaat dari segi optimasi Circuit.

# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager

pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)

Inisialisasi Estimator​

Buat instance qiskit.primitives.StatevectorEstimator.

from qiskit.primitives import StatevectorEstimator

estimator = StatevectorEstimator()

Jalankan dan dapatkan hasil​

Contoh ini hanya menggunakan satu Circuit (bertipe QuantumCircuit) dan satu observable.

Jalankan estimasi dengan memanggil metode StatevectorEstimator.run, yang mengembalikan instance dari objek PrimitiveJob. Kamu bisa mendapatkan hasil dari job (sebagai objek qiskit.primitives.PrimitiveResult) dengan metode qiskit.primitives.PrimitiveJob.result.

job = estimator.run([(circuit, observable, parameter_values)])
result = job.result()
print(f" > Result class: {type(result)}")
> Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>

Dapatkan nilai ekspektasi dari hasil​

Output hasil primitif berupa array dari objek PubResult, di mana setiap item dalam array adalah objek PubResult yang berisi dalam datanya array evaluasi yang sesuai dengan setiap kombinasi Circuit-observable dalam PUB.

Untuk mengambil nilai ekspektasi dan metadata untuk evaluasi Circuit pertama (dan dalam hal ini satu-satunya), kita harus mengakses data evaluasi untuk PUB 0:

print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")
> Expectation value: [4.         3.73205081 2.        ]
> Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}

Atur opsi run Estimator​

Secara default, Estimator referensi melakukan perhitungan statevector eksak berdasarkan kelas quantum_info.Statevector. Namun, ini bisa dimodifikasi untuk memperkenalkan efek dari sampling overhead (juga dikenal sebagai "shot noise").

Estimator menerima argumen precision yang mengekspresikan error bar yang harus dicapai oleh implementasi primitif untuk estimasi nilai ekspektasi. Ini adalah sampling overhead dan didefinisikan secara eksklusif di metode .run(). Ini memungkinkan kamu menyesuaikan opsi hingga ke tingkat PUB.

# Estimate expectation values for two PUBs, both with 0.05 precision.
precise_job = estimator.run(
[(circuit, observable, parameter_values)], precision=0.05
)

Untuk contoh lengkap, lihat halaman Contoh Primitives.

Gunakan Sampler referensi​

Implementasi referensi dari SamplerV2 di qiskit.primitives adalah kelas StatevectorSampler. Ia menerima Circuit dan parameter sebagai input dan mengembalikan hasil dari pengambilan sampel dari distribusi probabilitas output sebagai distribusi kuasi-probabilitas dari state output.

Kode berikut mempersiapkan input yang digunakan dalam contoh-contoh berikutnya. Perhatikan bahwa contoh-contoh ini menjalankan satu Circuit yang diparametrasi, tetapi kamu juga bisa menjalankan Sampler pada Circuit yang tidak diparametrasi.

from qiskit import QuantumCircuit

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw("mpl", style="iqp")

Output of the previous code cell

catatan

Setiap rangkaian kuantum yang diteruskan ke Sampler harus menyertakan pengukuran.

Transpile ke ISA circuits dan observable

Alur kerja primitif Qiskit Runtime memerlukan Circuit untuk diubah agar hanya menggunakan instruksi yang didukung oleh QPU (disebut sebagai ISA Circuit). Primitif referensi masih menerima instruksi abstrak, karena mereka mengandalkan simulasi statevector lokal, tetapi men-transpile Circuit mungkin tetap bermanfaat dari segi optimasi Circuit.

# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager

pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(qc)

Inisialisasi SamplerV2​

Buat instance qiskit.primitives.StatevectorSampler:

from qiskit.primitives import StatevectorSampler

sampler = StatevectorSampler()

Jalankan dan dapatkan hasil​

# execute 1 circuit with Sampler
job = sampler.run([circuit])
pub_result = job.result()[0]
print(f" > Result class: {type(pub_result)}")
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>

Primitif menerima beberapa PUB sebagai input, dan setiap PUB mendapatkan hasilnya sendiri. Oleh karena itu, kamu bisa menjalankan berbagai Circuit dengan kombinasi parameter/observable yang berbeda, dan mengambil hasil PUB:

from qiskit.transpiler import generate_preset_pass_manager

# create two circuits
circuit1 = circuit.copy()
circuit2 = circuit.copy()

# transpile circuits
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit1 = pm.run(circuit1)
isa_circuit2 = pm.run(circuit2)
# execute 2 circuits using Sampler
job = sampler.run([(isa_circuit1), (isa_circuit2)])
pub_result_1 = job.result()[0]
pub_result_2 = job.result()[1]
print(f" > Result class: {type(pub_result)}")
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>

Dapatkan distribusi probabilitas atau hasil pengukuran​

Sampel hasil pengukuran dikembalikan sebagai bitstring atau counts. Bitstring menampilkan hasil pengukuran, mempertahankan urutan shot di mana mereka diukur. Objek hasil Sampler mengorganisir data berdasarkan nama register klasik dari Circuit input mereka, untuk kompatibilitas dengan sirkuit dinamis.

catatan

Nama register klasik secara default adalah "meas". Nama ini akan digunakan nanti untuk mengakses bitstring pengukuran.

# Define quantum circuit with 2 qubits
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw()
β”Œβ”€β”€β”€β”      β–‘ β”Œβ”€β”
q_0: ─ H β”œβ”€β”€β– β”€β”€β”€β–‘β”€β”€Mβ”œβ”€β”€β”€
β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β” β–‘ β””β•₯β”˜β”Œβ”€β”
q_1: ────── X β”œβ”€β–‘β”€β”€β•«β”€β”€Mβ”œ
β””β”€β”€β”€β”˜ β–‘ β•‘ β””β•₯β”˜
meas: 2/══════════════╩══╩═
0 1
# Transpile circuit
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
# Run using sampler
result = sampler.run([circuit]).result()
# Access result data for PUB 0
data_pub = result[0].data
# Access bitstring for the classical register "meas"
bitstrings = data_pub.meas.get_bitstrings()
print(f"The number of bitstrings is: {len(bitstrings)}")
# Get counts for the classical register "meas"
counts = data_pub.meas.get_counts()
print(f"The counts are: {counts}")
The number of bitstrings is: 1024
The counts are: {'11': 515, '00': 509}

Ubah opsi run​

Secara default, Sampler referensi melakukan perhitungan statevector eksak berdasarkan kelas quantum_info.Statevector. Namun, ini bisa dimodifikasi untuk memperkenalkan efek dari sampling overhead (juga dikenal sebagai "shot noise"). Untuk membantu mengelola overhead ini, antarmuka Sampler menerima argumen shots yang dapat didefinisikan di tingkat PUB.

Contoh ini mengasumsikan kamu telah mendefinisikan dua Circuit.

# Sample two circuits at 128 shots each.
sampler.run([isa_circuit1, isa_circuit2], shots=128)
# Sample two circuits at different amounts of shots. The "None"s are necessary
# as placeholders
# for the lack of parameter values in this example.
sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])
<qiskit.primitives.primitive_job.PrimitiveJob at 0x7fa430e39dd0>

Untuk contoh lengkap, lihat halaman Contoh Primitives.

Langkah selanjutnya​

Rekomendasi
Source: IBM Quantum docs β€” updated 27 Apr 2026
English version on doQumentation β€” updated 7 Mei 2026
This translation based on the English version of 11 Mar 2026