Quantum computer, quantum key distribution algos

This commit is contained in:
Daniel Tsvetkov 2019-09-24 22:41:16 +02:00
commit e839ac4006
4 changed files with 244 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
venv
.idea

113
computer.py Normal file
View File

@ -0,0 +1,113 @@
import random
from math import sqrt, log
class Gate(list):
# Matrix multiplication
def __mul__(self, other):
rv = Gate()
for kol in range(len(other[0])):
for _ in range(len(self)):
rv.append([0])
# iterate through rows of a
for i in range(len(self)):
# iterate through columns of b
for j in range(len(other[0])):
# iterate through rows of b
for k in range(len(other)):
rv[i][j] += self[i][k] * other[k][j]
return rv
class Qubit(list):
# tensor multiplication
def __mul__(self, other):
rv = Qubit()
for i in self:
for j in other:
rv.append([i[0] * j[0]])
return rv
def measure(qubits):
"""
Measure result from computation
"""
probabilites = [q[0] ** 2 for q in qubits]
return bin(random.choices(
population=range(len(qubits)),
weights=probabilites
)[0])
_0 = Qubit([[1], [0]])
_1 = Qubit([[0], [1]])
I = Gate([
[1, 0],
[0, 1],
])
X = Gate([
[0, 1],
[1, 0],
])
Y = Gate([
[0, complex(0, -1)],
[complex(0, 1), 0],
])
Z = Gate([
[1, 0],
[0, -1],
])
CNOT = Gate([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
])
H = Gate([
[1 / sqrt(2), 1 / sqrt(2)],
[1 / sqrt(2), -1 / sqrt(2)],
])
def main():
# TEST IDENTITY
assert _1 == I * _1
assert _0 == I * _0
# TEST BIT-FLIP
assert _1 == X * _0
assert _0 == X * _1
# TEST CNOT GATE - Control * Target
# Control is FALSE, so target doesn't change
assert CNOT * (_0 * _0) == (_0 * _0)
assert CNOT * (_0 * _1) == (_0 * _1)
# Control is TRUE, so target MUST change
assert CNOT * (_1 * _0) == (_1 * _1)
assert CNOT * (_1 * _1) == (_1 * _0)
# TEST HADAMARD
superposition = Qubit(H * _0) * Qubit(H * _0)
print(superposition)
CNOT_superposition = Qubit(CNOT * superposition)
print(CNOT_superposition)
print(measure(CNOT_superposition))
# print(INVERTED_CNOT)
# TEST MY MEMORY
# rv = _0
# QUBITS = 23
# print(2**QUBITS)
# print("{:.1f} KB".format(2**QUBITS / 2**10))
# print("{:.1f} MB".format(2**QUBITS / 2**20))
# print("{:.1f} GB".format(2**QUBITS / 2**30))
# for i in range(QUBITS):
# rv *= _0
# print(len(rv))
if __name__ == "__main__":
main()

105
qkd.py Normal file
View File

@ -0,0 +1,105 @@
from dataclasses import dataclass, field
import random
STREAM_LENGTH = 100
@dataclass
class Photon(object):
basis: int
value: int
_measured: bool = False
_measured_value: bool = None
def measure(self, basis):
self._measured = True
if self.basis == basis:
return self.value
else:
if not self._measured:
self._measured_value = random.randint(0, 1)
return self._measured_value
def __repr__(self):
return '{}:{}'.format(self.basis, self.value)
@dataclass
class Alice:
_otp: list = None
bases: list = field(default_factory=list)
_values: list = field(default_factory=list)
def encode_qbit(self, value):
basis = random.randint(0, 1)
self.bases.append(basis)
return Photon(basis, value)
def generate_stream(self, stream_size=10):
for _ in range(stream_size):
qbit = random.randint(0, 1)
self._values.append(qbit)
yield self.encode_qbit(qbit)
def set_otp(self, other_correct):
self._otp = [v for c, v in zip(other_correct, self._values) if c]
def get_otp_length(self):
return len(self._otp)
@dataclass
class Bob:
correct: list = None
_otp: list = None
_bases: list = field(default_factory=list)
_values: list = field(default_factory=list)
def ingest_stream(self, stream):
for photon in stream:
basis = random.randint(0, 1)
self._bases.append(basis)
qbit_value = photon.measure(basis)
self._values.append(qbit_value)
def insecure_get_bases(self, other_bases):
self.correct = [not (a ^ b) for a, b in zip(self._bases, other_bases)]
self._otp = [v for c, v in zip(self.correct, self._values) if c]
@dataclass
class Mallory:
_bases: list = field(default_factory=list)
_values: list = field(default_factory=list)
def ingest_stream(self, stream):
for photon in stream:
basis = random.randint(0, 1)
self._bases.append(basis)
qbit_value = photon.measure(basis)
self._values.append(qbit_value)
yield photon
def main():
alice, bob, mallory = Alice(), Bob(), Mallory()
# Step 1. Generate a stream of random photons polarizations in a random basis
stream = alice.generate_stream(STREAM_LENGTH)
# Step 1.5 MALLORY ALSO INGESTS AND COPIES THE PHOTONS
stream = mallory.ingest_stream(stream)
# Step 2. Bob ingests the stream of photons
bob.ingest_stream(stream)
bob.insecure_get_bases(alice.bases)
alice.set_otp(bob.correct)
assert alice._otp == bob._otp
print("OTP Length: {}".format(alice.get_otp_length()))
if __name__ == "__main__":
main()

24
test_generator.py Normal file
View File

@ -0,0 +1,24 @@
def gen():
print("start gen")
for i in range(30):
print('gen {}'.format(i))
yield i
def ingest(stream):
print("start ingest+")
for number in stream:
print("injest {}".format(number))
yield number
def main():
print("main")
stream = gen()
something = ingest(stream)
for i in something:
print(i)
if __name__ == "__main__":
main()