Debug pekerjaan Qiskit Runtime
Versi paket
Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami merekomendasikan menggunakan versi ini atau yang lebih baru.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17
Sebelum mengirimkan workload Qiskit Runtime yang intensif sumber daya untuk dijalankan di hardware, kamu bisa menggunakan kelas Qiskit Runtime Neat (Noisy Estimator Analyzer Tool) untuk memverifikasi bahwa workload Estimator kamu sudah dikonfigurasi dengan benar, kemungkinan akan menghasilkan hasil yang akurat, menggunakan opsi yang paling tepat untuk masalah yang ditentukan, dan lainnya.
Neat melakukan Cliffordisasi terhadap sirkuit input untuk simulasi yang efisien, sambil mempertahankan struktur dan kedalamannya. Sirkuit Clifford mengalami tingkat noise yang serupa dan merupakan proksi yang baik untuk mempelajari sirkuit asli yang diminati.
Contoh-contoh berikut menggambarkan situasi di mana Neat bisa menjadi sumber daya yang berguna.
Pertama, impor paket yang relevan dan autentikasi ke layanan Qiskit Runtime.
Siapkan lingkunganβ
# Added by doQumentation β required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np
import random
from qiskit.circuit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
from qiskit_ibm_runtime.debug_tools import Neat
from qiskit_aer.noise import NoiseModel, depolarizing_error
# Choose the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Generate a preset pass manager
# This will be used to convert the abstract circuit to an equivalent Instruction Set Architecture (ISA) circuit.
pm = generate_preset_pass_manager(backend=backend, optimization_level=0)
# Set the random seed
random.seed(10)
Inisialisasi Circuit targetβ
Pertimbangkan sebuah Circuit enam-Qubit yang memiliki properti berikut:
- Bergantian antara rotasi
RZacak dan lapisan gateCNOT. - Memiliki struktur cermin, yaitu menerapkan unitary
Udiikuti oleh inversnya.
def generate_circuit(n_qubits, n_layers):
r"""
A function to generate a pseudo-random a circuit with ``n_qubits`` qubits and
``2*n_layers`` entangling layers of the type used in this notebook.
"""
# An array of random angles
angles = [
[random.random() for q in range(n_qubits)] for s in range(n_layers)
]
qc = QuantumCircuit(n_qubits)
qubits = list(range(n_qubits))
# do random circuit
for layer in range(n_layers):
# rotations
for q_idx, qubit in enumerate(qubits):
qc.rz(angles[layer][q_idx], qubit)
# cx gates
control_qubits = (
qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]
)
for qubit in control_qubits:
qc.cx(qubit, qubit + 1)
# undo random circuit
for layer in range(n_layers)[::-1]:
# cx gates
control_qubits = (
qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]
)
for qubit in control_qubits:
qc.cx(qubit, qubit + 1)
# rotations
for q_idx, qubit in enumerate(qubits):
qc.rz(-angles[layer][q_idx], qubit)
return qc
# Generate a random circuit
qc = generate_circuit(6, 3)
# Convert the abstract circuit to an equivalent ISA circuit.
isa_qc = pm.run(qc)
qc.draw("mpl", idle_wires=0)
Pilih operator Z Pauli tunggal sebagai observable dan gunakan untuk menginisialisasi primitive unified blocs (PUBs).
# Initialize the observables
obs = ["ZIIIII", "IZIIII", "IIZIII", "IIIZII", "IIIIZI", "IIIIIZ"]
print(f"Observables: {obs}")
# Map the observables to the backend's layout
isa_obs = [SparsePauliOp(o).apply_layout(isa_qc.layout) for o in obs]
# Initialize the PUBs, which consist of six-qubit circuits with `n_layers` 1, ..., 6
all_n_layers = [1, 2, 3, 4, 5, 6]
pubs = [(pm.run(generate_circuit(6, n)), isa_obs) for n in all_n_layers]
Observables: ['ZIIIII', 'IZIIII', 'IIZIII', 'IIIZII', 'IIIIZI', 'IIIIIZ']
Cliffordisasi Circuitβ
Circuit PUB yang telah didefinisikan sebelumnya bukan Clifford, yang membuatnya sulit untuk disimulasikan secara klasik. Namun, kamu bisa menggunakan metode Neat to_clifford untuk memetakannya ke Circuit Clifford agar simulasi lebih efisien. Metode to_clifford adalah pembungkus dari transpiler pass ConvertISAToClifford, yang juga bisa digunakan secara independen. Khususnya, metode ini menggantikan gate single-Qubit non-Clifford dalam Circuit asli dengan gate single-Qubit Clifford, tetapi tidak mengubah gate dua-Qubit, jumlah Qubit, atau kedalaman Circuit.
Lihat Simulasi efisien dari Circuit stabilizer dengan Qiskit Aer primitives untuk informasi lebih lanjut tentang simulasi Circuit Clifford.
Pertama, inisialisasi Neat.
# You could specify a custom `NoiseModel` here. If `None`, `Neat`
# pulls the noise model from the given backend
noise_model = None
# Initialize `Neat`
analyzer = Neat(backend, noise_model)
Selanjutnya, lakukan Cliffordisasi pada PUBs.
clifford_pubs = analyzer.to_clifford(pubs)
clifford_pubs[0].circuit.draw("mpl", idle_wires=0)
Aplikasi 1: Menganalisis dampak noise pada output Circuitβ
Contoh ini menunjukkan cara menggunakan Neat untuk mempelajari dampak berbagai model noise pada PUB sebagai fungsi kedalaman Circuit dengan menjalankan simulasi dalam kondisi ideal (ideal_sim) dan kondisi berisik (noisy_sim). Ini berguna untuk menetapkan ekspektasi kualitas hasil eksperimen sebelum menjalankan job pada QPU. Untuk mempelajari lebih lanjut tentang model noise, lihat Simulasi eksak dan berisik dengan Qiskit Aer primitives.
Hasil simulasi mendukung operasi matematis, sehingga dapat dibandingkan satu sama lain (atau dengan hasil eksperimental) untuk menghitung tolok ukur kualitas.
QPU bisa dipengaruhi oleh berbagai jenis noise. Model noise Qiskit Aer yang digunakan di sini hanya mensimulasikan sebagian dari noise tersebut, sehingga kemungkinan besar kurang parah dibandingkan noise pada QPU sungguhan.
Untuk detail tentang error apa saja yang disertakan saat menginisialisasi model noise dari QPU, lihat referensi API Aer NoiseModel.
Mulailah dengan melakukan simulasi klasik yang ideal dan berisik.
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
print(f"Ideal results:\n {ideal_results}\n")
# Perform a noisy simulation with the backend's noise model
noisy_results = analyzer.noisy_sim(clifford_pubs)
print(f"Noisy results:\n {noisy_results}\n")
Ideal results:
NeatResult([NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.]))])
Noisy results:
NeatResult([NeatPubResult(vals=array([0.99023438, 0.99609375, 0.9921875 , 0.99023438, 0.99414062,
0.99414062])), NeatPubResult(vals=array([0.984375 , 0.99414062, 0.98242188, 0.98828125, 0.98632812,
0.99414062])), NeatPubResult(vals=array([0.96679688, 0.97070312, 0.95898438, 0.97851562, 0.98046875,
0.98828125])), NeatPubResult(vals=array([0.9453125 , 0.953125 , 0.97070312, 0.96875 , 0.98242188,
0.99023438])), NeatPubResult(vals=array([0.93164062, 0.9375 , 0.953125 , 0.96875 , 0.96484375,
0.98046875])), NeatPubResult(vals=array([0.92578125, 0.921875 , 0.93359375, 0.953125 , 0.95898438,
0.9765625 ]))])
Selanjutnya, terapkan operasi matematis untuk menghitung selisih absolut. Sisa panduan ini menggunakan selisih absolut sebagai tolok ukur untuk membandingkan hasil ideal dengan hasil berisik atau eksperimental, tapi tolok ukur serupa bisa juga dibuat.
Selisih absolut menunjukkan bahwa dampak noise semakin besar seiring bertambahnya ukuran Circuit.
# Figure of merit: Absolute difference
def rdiff(res1, re2):
r"""The absolute difference between `res1` and re2`.
--> The closer to `0`, the better.
"""
d = abs(res1 - re2)
return np.round(d.vals * 100, 2)
for idx, (ideal_res, noisy_res) in enumerate(
zip(ideal_results, noisy_results)
):
vals = rdiff(ideal_res, noisy_res)
# Print the mean absolute difference for the observables
mean_vals = np.round(np.mean(vals), 2)
print(
f"Mean absolute difference between ideal and noisy results for circuits with {all_n_layers[idx]} layers:\n {mean_vals}%\n"
)
Mean absolute difference between ideal and noisy results for circuits with 1 layers:
0.72%
Mean absolute difference between ideal and noisy results for circuits with 2 layers:
1.17%
Mean absolute difference between ideal and noisy results for circuits with 3 layers:
2.6%
Mean absolute difference between ideal and noisy results for circuits with 4 layers:
3.16%
Mean absolute difference between ideal and noisy results for circuits with 5 layers:
4.4%
Mean absolute difference between ideal and noisy results for circuits with 6 layers:
5.5%
Kamu bisa mengikuti panduan kasar dan sederhana ini untuk meningkatkan Circuit jenis ini:
- Jika selisih absolut rata-rata lebih dari 90%, mitigasi kemungkinan tidak akan membantu.
- Jika selisih absolut rata-rata kurang dari 90%, Probabilistic Error Amplification (PEA) kemungkinan akan dapat meningkatkan hasilnya.
- Jika selisih absolut rata-rata kurang dari 80%, ZNE dengan gate folding juga kemungkinan dapat meningkatkan hasilnya.
Karena semua selisih absolut di atas kurang dari 90%, menerapkan PEA pada Circuit asli diharapkan dapat meningkatkan kualitas hasilnya. Kamu bisa menentukan model noise yang berbeda dalam analyzer. Contoh berikut melakukan pengujian yang sama tapi menambahkan model noise kustom.
# Set up a noise model with strength 0.02 on every two-qubit gate
noise_model = NoiseModel()
for qubits in backend.coupling_map:
noise_model.add_quantum_error(
depolarizing_error(0.02, 2), ["ecr", "cx"], qubits
)
# Update the analyzer's noise model
analyzer.noise_model = noise_model
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
# Perform a noisy simulation with the backend's noise model
noisy_results = analyzer.noisy_sim(clifford_pubs)
# Compare the results
for idx, (ideal_res, noisy_res) in enumerate(
zip(ideal_results, noisy_results)
):
values = rdiff(ideal_res, noisy_res)
# Print the mean absolute difference for the observables
mean_values = np.round(np.mean(values), 2)
print(
f"Mean absolute difference between ideal and noisy results for circuits with {all_n_layers[idx]} layers:\n {mean_values}%\n"
)
Mean absolute difference between ideal and noisy results for circuits with 1 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 2 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 3 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 4 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 5 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 6 layers:
0.0%
Seperti terlihat, dengan menggunakan model noise tertentu, kamu dapat mencoba mengukur dampak noise pada PUB (versi Cliffordized) yang ingin kamu jalankan sebelum menjalankannya pada QPU.
Aplikasi 2: Membandingkan berbagai strategiβ
Contoh ini menggunakan Neat untuk membantu mengidentifikasi opsi terbaik untuk PUB kamu. Untuk melakukan itu, pertimbangkan menjalankan masalah estimasi dengan PEA, yang tidak bisa disimulasikan dengan qiskit_aer. Kamu bisa menggunakan Neat untuk menentukan faktor amplifikasi noise mana yang paling cocok, lalu gunakan faktor-faktor tersebut saat menjalankan eksperimen asli pada QPU.
# Generate a circuit with six qubits and six layers
isa_qc = pm.run(generate_circuit(6, 3))
# Use the same observables as previously
pubs = [(isa_qc, isa_obs)]
clifford_pubs = analyzer.to_clifford(pubs)
noise_factors = [
[1, 1.1],
[1, 1.1, 1.2],
[1, 1.5, 2],
[1, 1.5, 2, 2.5, 3],
[1, 4],
]
# Run the PUBs on a QPU
estimator = Estimator(backend)
estimator.options.default_shots = 100000
estimator.options.twirling.enable_gates = True
estimator.options.twirling.enable_measure = True
estimator.options.twirling.shots_per_randomization = 100
estimator.options.resilience.measure_mitigation = True
estimator.options.resilience.zne_mitigation = True
estimator.options.resilience.zne.amplifier = "pea"
jobs = []
for factors in noise_factors:
estimator.options.resilience.zne.noise_factors = factors
jobs.append(estimator.run(clifford_pubs))
results = [job.result() for job in jobs]
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
# Look at the mean absolute difference to quickly tell the best choice for your options
for factors, res in zip(noise_factors, results):
d = rdiff(ideal_results[0], res[0])
print(
f"Mean absolute difference for factors {factors}:\n {np.round(np.mean(d), 2)}%\n"
)
Mean absolute difference for factors [1, 1.1]:
6.83%
Mean absolute difference for factors [1, 1.1, 1.2]:
8.76%
Mean absolute difference for factors [1, 1.5, 2]:
8.03%
Mean absolute difference for factors [1, 1.5, 2, 2.5, 3]:
10.17%
Mean absolute difference for factors [1, 4]:
8.02%
Hasil dengan selisih terkecil menunjukkan opsi mana yang sebaiknya dipilih.
Langkah berikutnyaβ
- Pelajari tentang Simulasi eksak dan berisik dengan Qiskit Aer primitives.
- Pelajari tentang opsi Qiskit Runtime yang tersedia.
- Pelajari tentang teknik mitigasi dan penekanan error.
- Kunjungi topik Transpile dengan pass managers.
- Pelajari cara melakukan transpile pada Circuit sebagai bagian dari alur kerja Qiskit patterns menggunakan Qiskit Runtime.
- Tinjau dokumentasi API Debugging tools.