107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
"""
|
||
Адаптированный пример алгоритма квантовой оценки фазы (QPE)
|
||
|
||
Для каждого значения целевой фазы φ (от 0.0 до 0.9) проверяется,
|
||
насколько точно QPE оценивает её с использованием заданного числа кубитов.
|
||
|
||
Схема QPE реализует следующую структуру:
|
||
|
||
---H---@------------------|QFT⁻¹|---M---
|
||
|
|
||
---H---@------------------|QFT⁻¹|---M---
|
||
|
|
||
---H---@------------------|QFT⁻¹|---M---
|
||
|
|
||
---|U|--|U²|--|U⁴|--|U⁸|------------
|
||
|
||
Измеренные биты M дают приближение фазы φ.
|
||
"""
|
||
|
||
import cirq
|
||
import numpy as np
|
||
|
||
|
||
def run_phase_estimation(u_gate, n_qubits: int, repetitions: int):
|
||
"""
|
||
Строит и симулирует схему QPE (Quantum Phase Estimation).
|
||
|
||
Параметры:
|
||
u_gate: унитарный оператор U, чья фаза e^{2πiφ} оценивается.
|
||
n_qubits: количество кубитов в регистре фазы (точность ~1/2^n).
|
||
repetitions: количество повторов измерений (для статистики).
|
||
"""
|
||
|
||
# Кубит, к которому применяется оператор U.
|
||
target = cirq.LineQubit(-1)
|
||
|
||
# Регистр для измерения фазы — n_qubits управляющих кубитов.
|
||
phase_qubits = cirq.LineQubit.range(n_qubits)
|
||
|
||
# Контролируемые операторы U^(2^i)
|
||
controlled_powers = [
|
||
(u_gate ** (2**i)).on(target).controlled_by(phase_qubits[i])
|
||
for i in range(n_qubits)
|
||
]
|
||
|
||
# Схема QPE:
|
||
circuit = cirq.Circuit(
|
||
cirq.H.on_each(*phase_qubits), # 1. Адамар на все управляющие кубиты
|
||
controlled_powers, # 2. Контролируемые степени U
|
||
cirq.qft(*phase_qubits, without_reverse=True)
|
||
** -1, # 3. Обратное квантовое преобразование Фурье
|
||
cirq.measure(*phase_qubits, key="phase"), # 4. Измерение регистра фазы
|
||
)
|
||
|
||
simulator = cirq.Simulator()
|
||
result = simulator.run(circuit, repetitions=repetitions)
|
||
return result
|
||
|
||
|
||
def example_gate(phi: float):
|
||
"""
|
||
Пример 1-кубитного унитарного оператора U:
|
||
U|0⟩ = e^{2πiφ}|0⟩,
|
||
U|1⟩ = |1⟩.
|
||
"""
|
||
matrix = np.array([[np.exp(2j * np.pi * phi), 0], [0, 1]])
|
||
return cirq.MatrixGate(matrix)
|
||
|
||
|
||
def experiment(n_qubits: int, repetitions=100):
|
||
"""
|
||
Запускает серию экспериментов для разных значений фазы φ.
|
||
"""
|
||
print(f"\nТест с {n_qubits} кубитами")
|
||
errors = []
|
||
|
||
for target_phi in np.arange(0, 1.0, 0.1):
|
||
gate = example_gate(target_phi)
|
||
result = run_phase_estimation(gate, n_qubits, repetitions)
|
||
|
||
# Наиболее часто встречающееся значение результата измерения
|
||
mode = result.data["phase"].mode()[0]
|
||
|
||
# Переводим измеренный результат в оценку фазы
|
||
phi_est = mode / (2**n_qubits)
|
||
|
||
print(
|
||
f"target={target_phi:0.4f}, estimate={phi_est:0.4f} = {mode}/{2**n_qubits}"
|
||
)
|
||
errors.append((target_phi - phi_est) ** 2)
|
||
|
||
rms = np.sqrt(np.mean(errors))
|
||
print(f"Среднеквадратичная ошибка (RMS): {rms:.4f}")
|
||
|
||
|
||
def main():
|
||
"""
|
||
Запускает эксперименты для разных количеств кубитов:
|
||
2, 4 и 8 — для демонстрации роста точности.
|
||
"""
|
||
for n in (2, 4, 8):
|
||
experiment(n, repetitions=200)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|