Shor9.py
This commit is contained in:
280
task11/shor9.py
Normal file
280
task11/shor9.py
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
import concurrent.futures
|
||||||
|
import random
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
import cirq
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def build_shor9_circuit(
|
||||||
|
p_error: float, with_correction: bool = True
|
||||||
|
) -> Tuple[cirq.Circuit, List[cirq.Qid]]:
|
||||||
|
"""Построение схемы кода Шора на 9 кубитах."""
|
||||||
|
qubits = [cirq.LineQubit(i) for i in range(9)]
|
||||||
|
circuit = cirq.Circuit()
|
||||||
|
|
||||||
|
# Подготовка исходного состояния логического кубита
|
||||||
|
circuit.append(cirq.rx(np.pi / 5)(qubits[0]))
|
||||||
|
|
||||||
|
# ----- Блок кодирования -----
|
||||||
|
# S1: CNOT 0->3
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[3]))
|
||||||
|
# S2: CNOT 0->6
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[6]))
|
||||||
|
# S3: H на 0, 3, 6
|
||||||
|
circuit.append(cirq.H.on_each(qubits[0], qubits[3], qubits[6]))
|
||||||
|
# S4: CNOT внутри блоков
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[1]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[3], qubits[4]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[6], qubits[7]))
|
||||||
|
# S5: еще CNOT внутри блоков
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[2]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[3], qubits[5]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[6], qubits[8]))
|
||||||
|
|
||||||
|
# ----- Блок шума -----
|
||||||
|
# ВАЖНО: как в оригинале - по одному кубиту проверяем вероятность ошибки
|
||||||
|
error_count = 0
|
||||||
|
error_idx = None
|
||||||
|
error_type = None
|
||||||
|
|
||||||
|
for idx in range(9):
|
||||||
|
if random.random() <= p_error:
|
||||||
|
error_count += 1
|
||||||
|
if error_count > 1:
|
||||||
|
break # Более одной ошибки - сразу неудача
|
||||||
|
error_idx = idx
|
||||||
|
error_type = "X" if random.random() > 0.5 else "Z"
|
||||||
|
|
||||||
|
if error_count == 1:
|
||||||
|
if error_type == "X":
|
||||||
|
circuit.append(cirq.X(qubits[error_idx]))
|
||||||
|
else:
|
||||||
|
circuit.append(cirq.Z(qubits[error_idx]))
|
||||||
|
|
||||||
|
# ----- Блок декодирования и коррекции -----
|
||||||
|
if with_correction and error_count <= 1:
|
||||||
|
# S6: обратное S4
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[1]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[3], qubits[4]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[6], qubits[7]))
|
||||||
|
# S7: обратное S5
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[2]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[3], qubits[5]))
|
||||||
|
circuit.append(cirq.CNOT(qubits[6], qubits[8]))
|
||||||
|
# S8: Toffoli для коррекции
|
||||||
|
circuit.append(cirq.TOFFOLI(qubits[1], qubits[2], qubits[0]))
|
||||||
|
circuit.append(cirq.TOFFOLI(qubits[4], qubits[5], qubits[3]))
|
||||||
|
circuit.append(cirq.TOFFOLI(qubits[7], qubits[8], qubits[6]))
|
||||||
|
# S9: обратное S3
|
||||||
|
circuit.append(cirq.H.on_each(qubits[0], qubits[3], qubits[6]))
|
||||||
|
# S10: обратное S1
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[3]))
|
||||||
|
# S11: обратное S2
|
||||||
|
circuit.append(cirq.CNOT(qubits[0], qubits[6]))
|
||||||
|
# S12: Toffoli между блоками
|
||||||
|
circuit.append(cirq.TOFFOLI(qubits[3], qubits[6], qubits[0]))
|
||||||
|
|
||||||
|
return circuit, qubits, error_count
|
||||||
|
|
||||||
|
|
||||||
|
def shor9(P: float = 0.05, debug: bool = False) -> Tuple[bool, int]:
|
||||||
|
"""Один прогон кода Шора - точно как в оригинале."""
|
||||||
|
simulator = cirq.Simulator()
|
||||||
|
|
||||||
|
# Сохраняем начальное состояние кубита 0
|
||||||
|
# Создаем схему только с подготовкой состояния
|
||||||
|
prep_circuit = cirq.Circuit(cirq.rx(np.pi / 5)(cirq.LineQubit(0)))
|
||||||
|
prep_result = simulator.simulate(prep_circuit)
|
||||||
|
|
||||||
|
# Получаем начальные амплитуды
|
||||||
|
initial_state = prep_result.final_state_vector
|
||||||
|
initial_0 = np.abs(initial_state[0]) ** 2
|
||||||
|
initial_1 = np.abs(initial_state[1]) ** 2
|
||||||
|
|
||||||
|
# Строим полную схему Шора
|
||||||
|
circuit, qubits, error_count = build_shor9_circuit(P, with_correction=True)
|
||||||
|
|
||||||
|
# Если более одной ошибки - сразу неудача (как в оригинале)
|
||||||
|
if error_count > 1:
|
||||||
|
return False, error_count
|
||||||
|
|
||||||
|
result = simulator.simulate(circuit)
|
||||||
|
final_state = result.final_state_vector
|
||||||
|
|
||||||
|
# Получаем амплитуды для кубита 0
|
||||||
|
# Вектор состояния имеет размер 2^9 = 512
|
||||||
|
# Индексы где q0=0: 0-255, где q0=1: 256-511
|
||||||
|
|
||||||
|
prob_0 = 0.0
|
||||||
|
prob_1 = 0.0
|
||||||
|
|
||||||
|
for i in range(512):
|
||||||
|
amp = final_state[i]
|
||||||
|
prob = np.abs(amp) ** 2
|
||||||
|
if i < 256: # q0 = 0
|
||||||
|
prob_0 += prob
|
||||||
|
else: # q0 = 1
|
||||||
|
prob_1 += prob
|
||||||
|
|
||||||
|
# Проверяем как в оригинале: np.isclose с tolerance 0.01
|
||||||
|
success = np.isclose(prob_0, initial_0, atol=0.01) and np.isclose(
|
||||||
|
prob_1, initial_1, atol=0.01
|
||||||
|
)
|
||||||
|
|
||||||
|
return success, error_count
|
||||||
|
|
||||||
|
|
||||||
|
def no_correction(P: float = 0.05, debug: bool = False) -> Tuple[bool, int]:
|
||||||
|
"""Модель без коррекции ошибок - точно как в оригинале."""
|
||||||
|
q = cirq.LineQubit(0)
|
||||||
|
|
||||||
|
# Сохраняем начальное состояние
|
||||||
|
prep_circuit = cirq.Circuit(cirq.rx(np.pi / 5)(q))
|
||||||
|
simulator = cirq.Simulator()
|
||||||
|
prep_result = simulator.simulate(prep_circuit)
|
||||||
|
initial_state = prep_result.final_state_vector
|
||||||
|
initial_0 = np.abs(initial_state[0]) ** 2
|
||||||
|
initial_1 = np.abs(initial_state[1]) ** 2
|
||||||
|
|
||||||
|
# Создаем схему с возможной ошибкой
|
||||||
|
circuit = cirq.Circuit(cirq.rx(np.pi / 5)(q))
|
||||||
|
|
||||||
|
# Применяем ошибку с вероятностью P
|
||||||
|
error_count = 0
|
||||||
|
if random.random() <= P:
|
||||||
|
error_count += 1
|
||||||
|
circuit.append(cirq.X(q))
|
||||||
|
|
||||||
|
result = simulator.simulate(circuit)
|
||||||
|
final_state = result.final_state_vector
|
||||||
|
|
||||||
|
final_0 = np.abs(final_state[0]) ** 2
|
||||||
|
final_1 = np.abs(final_state[1]) ** 2
|
||||||
|
|
||||||
|
# Проверяем как в оригинале, но с tolerance 0.0001
|
||||||
|
success = np.isclose(final_0, initial_0, atol=0.0001) and np.isclose(
|
||||||
|
final_1, initial_1, atol=0.0001
|
||||||
|
)
|
||||||
|
|
||||||
|
return success, error_count
|
||||||
|
|
||||||
|
|
||||||
|
def compute_failure_probability(
|
||||||
|
P: float, total_rounds: int = 500
|
||||||
|
) -> Tuple[float, float, float]:
|
||||||
|
"""Оценка вероятности сбоя для заданного P - точно как в оригинале."""
|
||||||
|
failure_count = 0
|
||||||
|
|
||||||
|
# Если P == 0, то вероятность ошибки = 0 (как в оригинале)
|
||||||
|
if P == 0:
|
||||||
|
return P, 0.0, 0.0
|
||||||
|
|
||||||
|
for _ in range(total_rounds):
|
||||||
|
correct, _ = shor9(P=P)
|
||||||
|
if not correct:
|
||||||
|
failure_count += 1
|
||||||
|
|
||||||
|
p_e = failure_count / total_rounds
|
||||||
|
p_e_nc = P # Как в оригинале: для схемы без коррекции вероятность ошибки = P
|
||||||
|
|
||||||
|
return P, p_e, p_e_nc
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_compute_failure_probability(
|
||||||
|
p_values: List[float], total_rounds: int = 500
|
||||||
|
):
|
||||||
|
"""Параллельный запуск оценки."""
|
||||||
|
results = []
|
||||||
|
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||||
|
results = list(
|
||||||
|
executor.map(
|
||||||
|
compute_failure_probability, p_values, [total_rounds] * len(p_values)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def theory(p: float) -> float:
|
||||||
|
"""Теоретическая оценка вероятности ошибки для кода Шора."""
|
||||||
|
return 1 - (1 + 8 * p) * (1 - p) ** 8
|
||||||
|
|
||||||
|
|
||||||
|
def shor9_withplot():
|
||||||
|
"""Построение графика."""
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
p = [0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]
|
||||||
|
p_e = []
|
||||||
|
p_e_nc = []
|
||||||
|
total_rounds = 100
|
||||||
|
|
||||||
|
print("Запуск моделирования...")
|
||||||
|
results = parallel_compute_failure_probability(p, total_rounds)
|
||||||
|
|
||||||
|
for P, p_e_value, p_e_nc_value in results:
|
||||||
|
p_e.append(p_e_value)
|
||||||
|
p_e_nc.append(p_e_nc_value)
|
||||||
|
print(f"P={P:.2f}: P_e={p_e_value:.4f} || P_e_nc={p_e_nc_value:.4f}")
|
||||||
|
|
||||||
|
# Построение графика
|
||||||
|
plt.figure(figsize=(10, 6))
|
||||||
|
|
||||||
|
# Экспериментальные данные
|
||||||
|
plt.plot(
|
||||||
|
p,
|
||||||
|
p_e,
|
||||||
|
marker="o",
|
||||||
|
label="С коррекцией (Шор)",
|
||||||
|
linestyle="-",
|
||||||
|
color="b",
|
||||||
|
alpha=0.7,
|
||||||
|
)
|
||||||
|
plt.plot(
|
||||||
|
p,
|
||||||
|
p_e_nc,
|
||||||
|
marker="s",
|
||||||
|
label="Без коррекции",
|
||||||
|
linestyle="-",
|
||||||
|
color="r",
|
||||||
|
alpha=0.7,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Теоретическая кривая
|
||||||
|
p_values = np.linspace(0, max(p), 100)
|
||||||
|
theory_values = [theory(x) for x in p_values]
|
||||||
|
plt.plot(
|
||||||
|
p_values,
|
||||||
|
theory_values,
|
||||||
|
label="Теория (Шор)",
|
||||||
|
color="green",
|
||||||
|
linestyle="--",
|
||||||
|
linewidth=2.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
plt.xlabel("Вероятность ошибки P")
|
||||||
|
plt.ylabel("Вероятность логической ошибки P_e")
|
||||||
|
plt.title("Зависимость вероятности ошибки от P")
|
||||||
|
plt.grid(True, alpha=0.3)
|
||||||
|
plt.legend()
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
# Сохраняем график
|
||||||
|
plt.savefig("shor_code_cirq.pdf", format="pdf", bbox_inches="tight")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Быстрый тест
|
||||||
|
print("Тестирование кода Шора...")
|
||||||
|
for P_test in [0, 0.05, 0.1]:
|
||||||
|
success, errors = shor9(P=P_test)
|
||||||
|
print(f"P={P_test:.2f}: Успех={success}, Ошибок={errors}")
|
||||||
|
|
||||||
|
print("\nТестирование без коррекции...")
|
||||||
|
for P_test in [0, 0.05, 0.1]:
|
||||||
|
success, errors = no_correction(P=P_test)
|
||||||
|
print(f"P={P_test:.2f}: Успех={success}, Ошибок={errors}")
|
||||||
|
|
||||||
|
# Основное моделирование
|
||||||
|
shor9_withplot()
|
||||||
Reference in New Issue
Block a user