2019-09-24 22:41:16 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2019-09-24 22:49:58 +02:00
|
|
|
def measure(qubits, times=10):
|
2019-09-24 22:41:16 +02:00
|
|
|
"""
|
2019-09-24 22:49:58 +02:00
|
|
|
Measure result from computation based on the qubit population
|
2019-09-24 22:41:16 +02:00
|
|
|
"""
|
|
|
|
probabilites = [q[0] ** 2 for q in qubits]
|
2019-09-24 22:49:58 +02:00
|
|
|
return [bin(m) for m in random.choices(
|
2019-09-24 22:41:16 +02:00
|
|
|
population=range(len(qubits)),
|
2019-09-24 22:49:58 +02:00
|
|
|
weights=probabilites,
|
|
|
|
k=times
|
|
|
|
)]
|
2019-09-24 22:41:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
_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
|
2019-09-24 22:49:58 +02:00
|
|
|
# Put two qubits in superposition
|
2019-09-24 22:41:16 +02:00
|
|
|
superposition = Qubit(H * _0) * Qubit(H * _0)
|
|
|
|
print(superposition)
|
2019-09-24 22:49:58 +02:00
|
|
|
# Entangle the qubits
|
|
|
|
entanglement = Qubit(CNOT * superposition)
|
|
|
|
print(entanglement)
|
|
|
|
|
|
|
|
# TODO: What does it mean to apply H gate on the entangled qubits???
|
|
|
|
# https://en.wikipedia.org/wiki/Controlled_NOT_gate#Behaviour_in_the_Hadamard_transformed_basis
|
|
|
|
# Should it be:
|
2019-09-24 22:55:54 +02:00
|
|
|
# q1 = Qubit(H * entanglement[:2])
|
|
|
|
# q2 = Qubit(H * entanglement[2:])
|
|
|
|
# But how does one get the 4x4 matrix of CNOT???
|
|
|
|
#
|
|
|
|
# q1 = Qubit(H * Qubit(entanglement[:2]))
|
|
|
|
# print(q1)
|
|
|
|
# q2 = Qubit(H * Qubit(entanglement[2:]))
|
|
|
|
# print(q2)
|
|
|
|
# print(q1 * q2)
|
2019-09-24 22:49:58 +02:00
|
|
|
|
|
|
|
# this should get us 1/4 chance for each combination of 00 01 10 and 10;
|
|
|
|
# measure 42 times
|
|
|
|
print(measure(entanglement, times=42))
|
2019-09-24 22:41:16 +02:00
|
|
|
|
|
|
|
# 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()
|