Квантова оцінка фази за допомогою Qiskit-функцій Q-CTRL
Оцінка використання: 40 секунд на процесорі Heron r2. (ПРИМІТКА: Це лише оцінка. Твій час виконання може відрізнятися.)
Передумови
Квантова оцінка фази (QPE) — це фундаментальний алгоритм у квантових обчисленнях, який лежить в основі багатьох важливих застосувань, таких як алгоритм Шора, оцінка енергії основного стану в квантовій хімії та задачі на власні значення. QPE оцінює фазу , пов'язану з власним станом унітарного оператора, закодовану у співвідношенні
і визначає її з точністю , використовуючи лічильних кубітів [1]. Підготувавши ці кубіти в суперпозиції, застосувавши контрольовані степені , а потім використавши обернене квантове перетворення Фур'є (QFT) для вилучення фази у двійково закодовані результати вимірювань, QPE створює розподіл ймовірностей із піком на бітових рядках, двійкові дроби яких апроксимують . В ідеальному випадку найбільш імовірний результат вимірювання безпосередньо відповідає двійковому розкладу фази, тоді як ймовірність інших результатів швидко зменшується зі збільшенням кількості лічильних кубітів. Однак виконання глибоких QPE-схем на апаратному забезпеченні створює труднощі: велика кількість кубітів та заплутуючих операцій робить алгоритм дуже чутливим до декогеренції та помилок вентилів. Це призводить до розширених і зміщених розподілів бітових рядків, що маскують справжню власну фазу. Як наслідок, бітовий рядок із найвищою ймовірністю може більше не відповідати правильному двійковому розкладу .
У цьому посібнику ми представляємо реалізацію алгоритму QPE з використанням інструментів придушення помилок та управління продуктивністю Fire Opal від Q-CTRL, що пропонуються як Qiskit-функція (див. документацію Fire Opal). Fire Opal автоматично застосовує передові оптимізації, включаючи динамічне розв'язування, покращення розташування кубітів та методи придушення помилок, що забезпечує результати з вищою точністю. Ці покращення наближають апаратні розподіли бітових рядків до тих, що отримані в безшумних симуляціях, щоб ти міг надійно ідентифікувати правильну власну фазу навіть в умовах впливу шуму.
Вимоги
Перш ніж розпочати цей посібник, переконайся, що у тебе встановлено наступне:
- Qiskit SDK v1.4 або новіший, з підтримкою візуалізації
- Qiskit Runtime v0.40 або новіший (
pip install qiskit-ibm-runtime) - Qiskit Functions Catalog v0.9.0 (
pip install qiskit-ibm-catalog) - Fire Opal SDK v9.0.2 або новіший (
pip install fire-opal) - Q-CTRL Visualizer v8.0.2 або новіший (
pip install qctrl-visualizer)
Налаштування
Спочатку автентифікуйся за допомогою твого API-ключа IBM Quantum. Потім вибери Qiskit-функцію наступним чином. (Цей код передбачає, що ти вже зберіг свій обліковий запис у локальному середовищі.)
# 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")
Крок 1: Відображення класичних вхідних даних на квантову задачу
У цьому посібнику ми демонструємо QPE для відновлення власної фази відомого однокубітного унітарного оператора. Унітарний оператор, фазу якого ми хочемо оцінити, — це однокубітний фазовий вентиль, що застосовується до цільового кубіта:
Ми готуємо його власний стан . Оскільки є власним вектором із власним значенням , власна фаза, яку потрібно оцінити, дорівнює:
Ми встановлюємо , тому справжня фаза дорівнює . QPE-схема реалізує контрольовані степені шляхом застосування контрольованих фазових обертань з кутами , а потім застосовує обернене QFT до лічильного регістра та вимірює його. Отримані бітові рядки концентруються навколо двійкового представлення .
Схема використовує лічильних кубітів (для встановлення точності оцінки) плюс один цільовий кубіт. Ми починаємо з визначення будівельних блоків, необхідних для реалізації QPE: квантове перетворення Фур'є (QFT) та його обернене, допоміжні функції для перетворення між десятковими та двійковими дробами власної фази, а також допоміжні функції для нормалізації необроблених підрахунків у ймовірності для порівняння результатів симуляції та апаратного забезпечення.
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
Крок 2: Оптимізація задачі для виконання на квантовому апаратному забезпеченні
Ми будуємо QPE-схему, підготувавши лічильні кубіти в суперпозиції, застосувавши контрольовані фазові обертання для кодування цільової власної фази та завершивши оберненим QFT перед вимірюванням.
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
Крок 3: Виконання за допомогою примітивів Qiskit
Ми встановлюємо кількість вимірювань та кубітів для експерименту і кодуємо цільову фазу , використовуючи двійкових розрядів. З цими параметрами ми будуємо QPE-схему, яка буде виконана на симуляції, стандартному апаратному забезпеченні та бекендах, покращених за допомогою 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
)
)
Запуск MPS-симуляції
Спочатку ми генеруємо еталонний розподіл за допомогою симулятора matrix_product_state та перетворюємо підрахунки в нормалізовані ймовірності для подальшого порівняння з результатами апаратного забезпечення.
# 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,
)
)
Запуск на апаратному забезпеченні
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)
Запуск на апаратному забезпеченні з Fire Opal
# Run the circuit using 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},
)
Крок 4: Постобробка та повернення результату у бажаному класичному форматі
# 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

Симуляція встановлює базовий рівень для правильної власної фази. Стандартні запуски на апаратному забезпеченні демонструють шум, який спотворює цей результат, оскільки шум розподіляє ймовірність між багатьма неправильними бітовими рядками. З використанням Q-CTRL Performance Management розподіл стає чіткішим, і правильний результат відновлюється, що забезпечує надійну QPE на цьому масштабі.
Джерела
[1] Лекція 7: Оцінка фази та факторизація. IBM Quantum Learning — Основи квантових алгоритмів. Отримано 3 жовтня 2025 року.
Опитування щодо посібника
Будь ласка, приділи хвилину, щоб залишити відгук про цей посібник. Твої враження допоможуть нам покращити наш контент та досвід користувачів.
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.