quantum/10_krisi_3qubits_game.py

177 lines
5.9 KiB
Python
Raw Permalink Normal View History

2020-03-27 19:48:18 +01:00
import random
from collections import defaultdict
import numpy as np
2020-03-28 17:21:13 +01:00
from lib import *
2020-03-27 19:48:18 +01:00
def test_krisi_measurement_2():
CASE_IDENTICAL = "identical"
CASE_ORTHOGONAL = "orthogonal"
def perform_exp(case):
# produce angles with uniform distribution on the sphere
t = round(np.random.uniform(0, 1), 10)
theta0 = np.arccos(1 - 2 * t)
phi0 = round(np.random.uniform(0, 2 * np.pi), 10)
# rotate the 0th qubit in (theta, phi)
q0 = State.from_bloch_angles(theta0, phi0)
# rotate the 1st qubit depending on the case we are exploring...
if case == CASE_IDENTICAL:
# ... for identical we are rotating the 1st qubit the same angles as
# the 0th
theta1, phi1 = theta0, phi0
else:
# for orthogonal we rotate the 1st qubit in 90 degrees
# orthogonal to the first
theta1, phi1 = theta0 + np.pi, phi0
q1 = State.from_bloch_angles(theta1, phi1)
# Measure in the Bell's basis
st = State(q0 * q1)
2020-03-28 10:41:37 +01:00
meas = st.measure(basis=bell_basis)
2020-03-27 19:48:18 +01:00
return meas
correct = 0
cases = defaultdict(int)
results = defaultdict(int)
for i in range(1000):
case = random.choice([CASE_IDENTICAL, CASE_ORTHOGONAL])
cases[case] += 1
result = perform_exp(case=case)
results[result] += 1
if result == '11':
guess = CASE_ORTHOGONAL
assert guess == case
else:
guess = CASE_IDENTICAL
if guess == case:
correct += 1
print("Correct: {}".format(correct))
# print("Results: {}".format(results))
# print("Cases: {}".format(cases))
def test_krisi_measurement_3():
2020-03-27 20:13:12 +01:00
iterations = 400
2020-03-29 20:38:08 +02:00
beta = np.pi + 0.62
2020-03-27 20:13:12 +01:00
2020-03-27 19:48:18 +01:00
CASE_ID_ID = "id_id"
CASE_ID_ORT = "id_ort"
CASE_ORT_ID = "ort_id"
CASE_ORT_ORT = "ort_ort"
2020-03-27 20:13:12 +01:00
case_choices = [CASE_ID_ID, CASE_ID_ORT, CASE_ORT_ID, CASE_ORT_ORT]
2020-03-29 20:38:08 +02:00
b_0 = State((1 / np.sqrt(2)) * (s("|100>") + s("|010>")))
b_1 = State((1 / np.sqrt(2)) * (s("|011>") + s("|101>")))
2020-03-27 19:48:18 +01:00
basis = [
2020-03-30 15:51:17 +02:00
s("|000>", name="B0"),
State(np.cos(beta) * b_0 + np.sin(beta) * s("|001>"), name="B1"),
State(-np.sin(beta) * b_0 + np.cos(beta) * s("|001>"), name="B2"),
State((1 / np.sqrt(2)) * (s("|100>") - s("|010>")), name="B3"),
State((1 / np.sqrt(2)) * (s("|011>") - s("|101>")), name="B4"),
State(np.cos(beta) * b_1 + np.sin(beta) * s("|001>"), name="B5"),
State(-np.sin(beta) * b_1 + np.cos(beta) * s("|001>"), name="B6"),
s("|111>", name="B7"),
2020-03-27 19:48:18 +01:00
]
def perform_exp(case):
# produce angles with uniform distribution on the sphere
t = round(np.random.uniform(0, 1), 10)
theta0 = np.arccos(1 - 2 * t)
phi0 = round(np.random.uniform(0, 2 * np.pi), 10)
# rotate the 0th qubit in (theta, phi)
2020-03-28 17:21:13 +01:00
q1 = State.from_bloch_angles(theta0, phi0)
2020-03-27 19:48:18 +01:00
# rotate the 1st qubit depending on the case we are exploring...
if case == CASE_ID_ID:
theta1, phi1 = theta0, phi0
theta2, phi2 = theta0, phi0
elif case == CASE_ID_ORT:
theta1, phi1 = theta0, phi0
theta2, phi2 = theta0 + np.pi, phi0
elif case == CASE_ORT_ID:
theta1, phi1 = theta0 + np.pi, phi0
theta2, phi2 = theta0, phi0
else:
# CASE_ORT_ORT
theta1, phi1 = theta0 + np.pi, phi0
theta2, phi2 = theta0 + np.pi, phi0
2020-03-28 17:21:13 +01:00
q2 = State.from_bloch_angles(theta1, phi1)
q1q2_st = State(q1*q2)
2020-03-29 20:38:08 +02:00
# meas1 = q1q2_st.measure(basis=bell_basis)
# if meas1 == '11':
# return 'discarded'
2020-03-27 19:48:18 +01:00
2020-03-29 20:38:08 +02:00
P_minus = b_psi_m.x(b_psi_m)
2020-03-28 17:21:13 +01:00
P_s = b_psi_p.x(b_psi_p) + b_phi_m.x(b_phi_m) + b_phi_p.x(b_phi_p)
2020-03-29 20:38:08 +02:00
# vec = MeasurementOperator(P_minus.m).on(q1q2_st)
# if np.all(vec.m.transpose() == np.zeros(4)):
# return 'identical'
vec2 = MeasurementOperator(P_s.m).on(q1q2_st)
post_state = State(State.normalize(vec2))
2020-03-28 17:21:13 +01:00
if case == CASE_ID_ID:
assert post_state == q1q2_st
elif case in [CASE_ORT_ID, CASE_ORT_ORT]:
assert post_state != q1q2_st
q3 = State.from_bloch_angles(theta2, phi2)
2020-03-29 20:38:08 +02:00
meas = State(post_state * q3).measure(basis=basis)
2020-03-28 17:21:13 +01:00
# # TODO: This part measures the first two qubits in Bell basis, then:
# # 1. constructs a new pure state
# # (e.g. if result was 11, constructs |11>)
# # 2. Combines this new pure state with the third qubit
# MEASURE_FIRST_BELL = False
# if MEASURE_FIRST_BELL:
# # Measure in the Bell's basis
# st = State(q1 * q2)
# meas = st.measure(basis=bell_basis)
# new_st = s("|" + meas + ">")
# st = State(new_st * q3)
# else:
# # TODO: -OR- alternatively - measure all three without measuring in
# # Bell first
# st = State(q1 * q2 * q3)
#
# # Measure in the 8D basis
# meas = st.measure(basis=basis)
2020-03-27 19:48:18 +01:00
return meas
def krisi_3_format_results(results):
2020-03-30 15:51:17 +02:00
all_pos = basis
2020-03-27 19:48:18 +01:00
print("Results:")
2020-03-27 20:13:12 +01:00
for case in case_choices:
rv = results.get(case)
2020-03-27 19:48:18 +01:00
print("{}:".format(case))
2020-03-30 15:51:17 +02:00
print(" raw : {}".format(rv.items()))
2020-03-27 19:48:18 +01:00
case_total = sum(rv.values())
print(" total: {}".format(case_total))
for pos in all_pos:
value = rv.get(pos, 0)
2020-03-28 17:21:13 +01:00
percent = (value / case_total)*100
print(" {} : {:3d} ({:.1f}%)".format(pos, value, percent))
2020-03-27 19:48:18 +01:00
results = defaultdict(lambda: defaultdict(int))
2020-03-27 20:13:12 +01:00
for i in range(iterations):
case = random.choice(case_choices)
2020-03-27 19:48:18 +01:00
result = perform_exp(case=case)
results[case][result] += 1
krisi_3_format_results(results)
if __name__ == "__main__":
# test_krisi_measurement_2()
test_krisi_measurement_3()