Quantum computer, quantum key distribution algos
This commit is contained in:
commit
e839ac4006
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
venv
|
||||||
|
.idea
|
113
computer.py
Normal file
113
computer.py
Normal 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
105
qkd.py
Normal 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
24
test_generator.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user