Quantum Phase Estimation dengan Qiskit Functions dari Q-CTRL
Estimasi penggunaan: 40 detik pada prosesor Heron r2. (CATATAN: Ini hanya estimasi. Waktu aktual kamu bisa berbeda.)
Latar Belakang
Quantum Phase Estimation (QPE) adalah algoritma dasar dalam komputasi kuantum yang menjadi fondasi bagi banyak aplikasi penting seperti algoritma Shor, estimasi energi ground-state dalam kimia kuantum, dan masalah nilai eigen. QPE mengestimasi fase yang terkait dengan eigenstate dari operator uniter, yang dikodekan dalam relasi
dan menentukannya dengan presisi menggunakan counting qubit [1]. Dengan menyiapkan qubit-qubit ini dalam superposisi, menerapkan perpangkatan terkontrol dari , lalu menggunakan inverse Quantum Fourier Transform (QFT) untuk mengekstrak fase ke dalam hasil pengukuran yang dikodekan secara biner, QPE menghasilkan distribusi probabilitas yang terpusat pada bitstring yang pecahan binernya mendekati . Pada kasus ideal, hasil pengukuran dengan probabilitas tertinggi langsung berkorespondensi dengan ekspansi biner dari fase tersebut, sementara probabilitas hasil lainnya menurun dengan cepat seiring bertambahnya jumlah counting qubit. Namun, menjalankan Circuit QPE yang dalam pada perangkat keras memiliki tantangan tersendiri: banyaknya qubit dan operasi entangling membuat algoritma ini sangat sensitif terhadap dekoherensi dan kesalahan Gate. Hal ini menyebabkan distribusi bitstring menjadi lebih lebar dan bergeser, sehingga menyembunyikan eigenphase yang sebenarnya. Akibatnya, bitstring dengan probabilitas tertinggi mungkin tidak lagi berkorespondensi dengan ekspansi biner yang benar dari .
Dalam tutorial ini, kita mempresentasikan implementasi algoritma QPE menggunakan alat penekanan kesalahan dan manajemen performa Fire Opal dari Q-CTRL, yang ditawarkan sebagai Qiskit Function (lihat dokumentasi Fire Opal). Fire Opal secara otomatis menerapkan optimasi canggih, termasuk dynamical decoupling, peningkatan layout qubit, dan teknik penekanan kesalahan, sehingga menghasilkan output dengan fidelitas lebih tinggi. Peningkatan ini membuat distribusi bitstring dari perangkat keras lebih mendekati yang diperoleh dari simulasi tanpa noise, sehingga kamu bisa mengidentifikasi eigenphase yang benar dengan andal meski di bawah pengaruh noise.
Persyaratan
Sebelum memulai tutorial ini, pastikan kamu sudah menginstal hal-hal berikut:
- Qiskit SDK v1.4 atau lebih baru, dengan dukungan visualisasi
- Qiskit Runtime v0.40 atau lebih baru (
pip install qiskit-ibm-runtime) - Qiskit Functions Catalog v0.9.0 (
pip install qiskit-ibm-catalog) - Fire Opal SDK v9.0.2 atau lebih baru (
pip install fire-opal) - Q-CTRL Visualizer v8.0.2 atau lebih baru (
pip install qctrl-visualizer)
Pengaturan
Pertama, autentikasi menggunakan API key IBM Quantum kamu. Kemudian, pilih Qiskit Function seperti berikut. (Kode ini mengasumsikan kamu sudah menyimpan akun ke lingkungan lokal kamu.)
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qctrlvisualizer qiskit qiskit-aer qiskit-ibm-catalog qiskit-ibm-runtime
from qiskit import QuantumCircuit
import numpy as np
import matplotlib.pyplot as plt
import qiskit
from qiskit import qasm2
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
import qctrlvisualizer as qv
from qiskit_ibm_catalog import QiskitFunctionsCatalog
plt.style.use(qv.get_qctrl_style())
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access Function
perf_mgmt = catalog.load("q-ctrl/performance-management")
Langkah 1: Petakan input klasik ke masalah kuantum
Dalam tutorial ini, kita mengilustrasikan QPE untuk memulihkan eigenphase dari sebuah uniter satu qubit yang sudah diketahui. Uniter yang fasenya ingin kita estimasi adalah gate fase satu qubit yang diterapkan ke target qubit:
Kita siapkan eigenstate-nya . Karena adalah eigenvector dari dengan nilai eigen , eigenphase yang perlu diestimasi adalah:
Kita tetapkan , sehingga fase ground-truth-nya adalah . Circuit QPE mengimplementasikan perpangkatan terkontrol dengan menerapkan rotasi fase terkontrol dengan sudut , lalu menerapkan inverse QFT ke counting register dan mengukurnya. Bitstring yang dihasilkan terkonsentrasi di sekitar representasi biner dari .
Circuit ini menggunakan counting qubit (untuk mengatur presisi estimasi) ditambah satu target qubit. Kita mulai dengan mendefinisikan blok-blok pembangun yang diperlukan untuk mengimplementasikan QPE: Quantum Fourier Transform (QFT) dan inversnya, fungsi utilitas untuk memetakan antara pecahan desimal dan biner dari eigenphase, serta helper untuk menormalisasi hitungan mentah menjadi probabilitas guna membandingkan hasil simulasi dan perangkat keras.
def inverse_quantum_fourier_transform(quantum_circuit, number_of_qubits):
"""
Apply an inverse Quantum Fourier Transform the first `number_of_qubits` qubits in the
`quantum_circuit`.
"""
for qubit in range(number_of_qubits // 2):
quantum_circuit.swap(qubit, number_of_qubits - qubit - 1)
for j in range(number_of_qubits):
for m in range(j):
quantum_circuit.cp(-np.pi / float(2 ** (j - m)), m, j)
quantum_circuit.h(j)
return quantum_circuit
def bitstring_count_to_probabilities(data, shot_count):
"""
This function turns an unsorted dictionary of bitstring counts into a sorted dictionary
of probabilities.
"""
# Turn the bitstring counts into probabilities.
probabilities = {
bitstring: bitstring_count / shot_count
for bitstring, bitstring_count in data.items()
}
sorted_probabilities = dict(
sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
)
return sorted_probabilities
Langkah 2: Optimalkan masalah untuk eksekusi di perangkat keras kuantum
Kita membangun Circuit QPE dengan menyiapkan counting qubit dalam superposisi, menerapkan rotasi fase terkontrol untuk mengkodekan eigenphase target, dan mengakhirinya dengan inverse QFT sebelum pengukuran.
def quantum_phase_estimation_benchmark_circuit(
number_of_counting_qubits, phase
):
"""
Create the circuit for quantum phase estimation.
Parameters
----------
number_of_counting_qubits : The number of qubits in the circuit.
phase : The desired phase.
Returns
-------
QuantumCircuit
The quantum phase estimation circuit for `number_of_counting_qubits` qubits.
"""
qc = QuantumCircuit(
number_of_counting_qubits + 1, number_of_counting_qubits
)
target = number_of_counting_qubits
# |1> eigenstate for the single-qubit phase gate
qc.x(target)
# Hadamards on counting register
for q in range(number_of_counting_qubits):
qc.h(q)
# ONE controlled phase per counting qubit: cp(phase * 2**k)
for k in range(number_of_counting_qubits):
qc.cp(phase * (1 << k), k, target)
qc.barrier()
# Inverse QFT on counting register
inverse_quantum_fourier_transform(qc, number_of_counting_qubits)
qc.barrier()
for q in range(number_of_counting_qubits):
qc.measure(q, q)
return qc
Langkah 3: Eksekusi menggunakan primitif Qiskit
Kita menetapkan jumlah shot dan qubit untuk eksperimen, lalu mengkodekan fase target menggunakan digit biner. Dengan parameter-parameter ini, kita membangun Circuit QPE yang akan dieksekusi pada simulasi, perangkat keras default, dan Backend yang ditingkatkan dengan Fire Opal.
shot_count = 10000
num_qubits = 35
phase = (1 / 6) * 2 * np.pi
circuits_quantum_phase_estimation = (
quantum_phase_estimation_benchmark_circuit(
number_of_counting_qubits=num_qubits, phase=phase
)
)
Jalankan simulasi MPS
Pertama, kita buat distribusi referensi menggunakan simulator matrix_product_state dan konversi hitungan menjadi probabilitas yang ternormalisasi untuk dibandingkan nantinya dengan hasil perangkat keras.
# Run the algorithm on the IBM Aer simulator.
aer_simulator = AerSimulator(method="matrix_product_state")
# Transpile the circuits for the simulator.
transpiled_circuits = qiskit.transpile(
circuits_quantum_phase_estimation, aer_simulator
)
simulated_result = (
aer_simulator.run(transpiled_circuits, shots=shot_count)
.result()
.get_counts()
)
simulated_result_probabilities = []
simulated_result_probabilities.append(
bitstring_count_to_probabilities(
simulated_result,
shot_count=shot_count,
)
)
Jalankan di perangkat keras
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
isa_circuits = pm.run(circuits_quantum_phase_estimation)
# Run the algorithm with IBM default.
sampler = Sampler(backend)
# Run all circuits using Qiskit Runtime.
ibm_default_job = sampler.run([isa_circuits], shots=shot_count)
Jalankan di perangkat keras dengan Fire Opal
# Run the circuit using the sampler
fire_opal_job = perf_mgmt.run(
primitive="sampler",
pubs=[qasm2.dumps(circuits_quantum_phase_estimation)],
backend_name=backend.name,
options={"default_shots": shot_count},
)
Langkah 4: Pasca-proses dan kembalikan hasil dalam format klasik yang diinginkan
# Retrieve results.
ibm_default_result = ibm_default_job.result()
ibm_default_probabilities = []
for idx, pub_result in enumerate(ibm_default_result):
ibm_default_probabilities.append(
bitstring_count_to_probabilities(
pub_result.data.c0.get_counts(),
shot_count=shot_count,
)
)
fire_opal_result = fire_opal_job.result()
fire_opal_probabilities = []
for idx, pub_result in enumerate(fire_opal_result):
fire_opal_probabilities.append(
bitstring_count_to_probabilities(
pub_result.data.c0.get_counts(),
shot_count=shot_count,
)
)
data = {
"simulation": simulated_result_probabilities,
"default": ibm_default_probabilities,
"fire_opal": fire_opal_probabilities,
}
def plot_distributions(
data,
number_of_counting_qubits,
top_k=None,
by="prob",
shot_count=None,
):
def nrm(d):
s = sum(d.values())
return {k: (v / s if s else 0.0) for k, v in d.items()}
def as_float(d):
return {k: float(v) for k, v in d.items()}
def to_space(d):
if by == "prob":
return nrm(as_float(d))
else:
if shot_count and 0.99 <= sum(d.values()) <= 1.01:
return {
k: v * float(shot_count) for k, v in as_float(d).items()
}
else:
return as_float(d)
def topk(d, k):
items = sorted(d.items(), key=lambda kv: kv[1], reverse=True)
return items[: (k or len(d))]
phase = "1/6"
sim = to_space(data["simulation"])
dft = to_space(data["default"])
qct = to_space(data["fire_opal"])
correct = max(sim, key=sim.get) if sim else None
print("Correct result:", correct)
sim_items = topk(sim, top_k)
dft_items = topk(dft, top_k)
qct_items = topk(qct, top_k)
sim_keys, y_sim = zip(*sim_items) if sim_items else ([], [])
dft_keys, y_dft = zip(*dft_items) if dft_items else ([], [])
qct_keys, y_qct = zip(*qct_items) if qct_items else ([], [])
fig, axes = plt.subplots(3, 1, layout="constrained")
ylab = "Probabilities"
def panel(ax, keys, ys, title, color):
x = np.arange(len(keys))
bars = ax.bar(x, ys, color=color)
ax.set_title(title)
ax.set_ylabel(ylab)
ax.set_xticks(x)
ax.set_xticklabels(keys, rotation=90)
ax.set_xlabel("Bitstrings")
if correct in keys:
i = keys.index(correct)
bars[i].set_edgecolor("black")
bars[i].set_linewidth(2)
return max(ys, default=0.0)
c_sim, c_dft, c_qct = (
qv.QCTRL_STYLE_COLORS[5],
qv.QCTRL_STYLE_COLORS[1],
qv.QCTRL_STYLE_COLORS[0],
)
m1 = panel(axes[0], list(sim_keys), list(y_sim), "Simulation", c_sim)
m2 = panel(axes[1], list(dft_keys), list(y_dft), "Default", c_dft)
m3 = panel(axes[2], list(qct_keys), list(y_qct), "Q-CTRL", c_qct)
for ax, m in zip(axes, (m1, m2, m3)):
ax.set_ylim(0, 1.05 * (m or 1.0))
for ax in axes:
ax.label_outer()
fig.suptitle(
rf"{number_of_counting_qubits} counting qubits, $2\pi\varphi$={phase}"
)
fig.set_size_inches(20, 10)
plt.show()
experiment_index = 0
phase_index = 0
distributions = {
"simulation": data["simulation"][phase_index],
"default": data["default"][phase_index],
"fire_opal": data["fire_opal"][phase_index],
}
plot_distributions(
distributions, num_qubits, top_k=100, by="prob", shot_count=shot_count
)
Correct result: 00101010101010101010101010101010101

Simulasi menetapkan baseline untuk eigenphase yang benar. Eksekusi di perangkat keras default menunjukkan noise yang mengaburkan hasil ini, karena noise menyebarkan probabilitas ke banyak bitstring yang salah. Dengan Q-CTRL Performance Management, distribusinya menjadi lebih tajam dan hasil yang benar dapat dipulihkan, sehingga QPE pada skala ini bisa diandalkan.
Referensi
[1] Lecture 7: Phase Estimation and Factoring. IBM Quantum Learning - Fundamentals of quantum algorithms. Retrieved October 3, 2025.
Survei tutorial
Luangkan sebentar waktu kamu untuk memberikan masukan tentang tutorial ini. Pendapatmu akan membantu kami meningkatkan konten dan pengalaman pengguna.
Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.