quantum framework + dense coding
This commit is contained in:
parent
b80fa8e3e0
commit
32ba69a3b2
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
venv
|
venv
|
||||||
.idea
|
.idea
|
||||||
|
__pycache__
|
66
04_qkd_2.py
66
04_qkd_2.py
@ -3,6 +3,8 @@ import random
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# should print some debugging statements?
|
# should print some debugging statements?
|
||||||
|
from lib_q_computer_old import _0, I, X, H, measure, run_qbit_tests
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
# How long should be the stream - in general about half of the stream
|
# How long should be the stream - in general about half of the stream
|
||||||
@ -13,70 +15,6 @@ STREAM_LENGTH = 20
|
|||||||
# The message that Alice wants to send to Bob
|
# The message that Alice wants to send to Bob
|
||||||
_ALICE_MESSAGE = 'd'
|
_ALICE_MESSAGE = 'd'
|
||||||
|
|
||||||
# |0> and |1>
|
|
||||||
_0 = np.array([[1],
|
|
||||||
[0]])
|
|
||||||
_1 = np.array([[0],
|
|
||||||
[1]])
|
|
||||||
|
|
||||||
# |+> and |->
|
|
||||||
_p = np.array([[1 / np.sqrt(2)],
|
|
||||||
[1 / np.sqrt(2)]])
|
|
||||||
_m = np.array([[1 / np.sqrt(2)],
|
|
||||||
[-1 / np.sqrt(2)]])
|
|
||||||
|
|
||||||
# Gates - Identity, Pauli X and Hadamard
|
|
||||||
I = np.array([[1, 0],
|
|
||||||
[0, 1]])
|
|
||||||
X = np.array([[0, 1],
|
|
||||||
[1, 0]])
|
|
||||||
H = np.array([[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
|
||||||
[1 / np.sqrt(2), -1 / np.sqrt(2)]])
|
|
||||||
|
|
||||||
|
|
||||||
def measure_probability(qbit):
|
|
||||||
"""
|
|
||||||
In a qbit [a, b] normalized: |a|^2 + |b|^2 = 1
|
|
||||||
Probability of 0 is |a|^2 and 1 with prob |b|^2
|
|
||||||
|
|
||||||
:returns: tuple of probabilities to measure 0 or 1"""
|
|
||||||
return np.abs(qbit[0][0]) ** 2, np.abs(qbit[1][0]) ** 2
|
|
||||||
|
|
||||||
|
|
||||||
def measure(qbit):
|
|
||||||
"""
|
|
||||||
This gets a random choice of either 0 and 1 with weights
|
|
||||||
based on the probabilities of the qbit
|
|
||||||
|
|
||||||
:returns: classical bit based on qbit probabilities"""
|
|
||||||
return random.choices([0, 1], measure_probability(qbit))[0]
|
|
||||||
|
|
||||||
|
|
||||||
def run_qbit_tests():
|
|
||||||
# asserts are sets of tests to check if mathz workz
|
|
||||||
|
|
||||||
# Identity: verify that I|0> == |0> and I|1> == |0>
|
|
||||||
assert np.array_equal(I.dot(_0), _0)
|
|
||||||
assert np.array_equal(I.dot(_1), _1)
|
|
||||||
|
|
||||||
# Pauli X: verify that X|0> == |1> and X|1> == |0>
|
|
||||||
assert np.array_equal(X.dot(_0), _1)
|
|
||||||
assert np.array_equal(X.dot(_1), _0)
|
|
||||||
|
|
||||||
# measure probabilities in sigma_x of |0> and |1>
|
|
||||||
# using allclose since dealing with floats
|
|
||||||
assert np.allclose(measure_probability(_0), (1.0, 0.0))
|
|
||||||
assert np.allclose(measure_probability(_1), (0.0, 1.0))
|
|
||||||
|
|
||||||
# applying Hadamard puts the qbit in orthogonal +/- basis
|
|
||||||
assert np.array_equal(H.dot(_0), _p)
|
|
||||||
assert np.array_equal(H.dot(_1), _m)
|
|
||||||
|
|
||||||
# measure probabilities in sigma_x of |+> and |->
|
|
||||||
# using allclose since dealing with floats
|
|
||||||
assert np.allclose(measure_probability(_p), (0.5, 0.5))
|
|
||||||
assert np.allclose(measure_probability(_m), (0.5, 0.5))
|
|
||||||
|
|
||||||
|
|
||||||
def bases_to_classical(qbits):
|
def bases_to_classical(qbits):
|
||||||
"""
|
"""
|
||||||
|
54
05_dense_coding.py
Normal file
54
05_dense_coding.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
from lib_q_computer import Qubit, __0, H, CNOT, I, X, Z
|
||||||
|
|
||||||
|
|
||||||
|
def quantum_dense_coding():
|
||||||
|
q1 = Qubit(__0)
|
||||||
|
q2 = Qubit(__0)
|
||||||
|
|
||||||
|
print("Hadamard on q1")
|
||||||
|
q1 = H.on(q1)
|
||||||
|
print(q1)
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Bell state")
|
||||||
|
bell = CNOT.on([q1, q2])
|
||||||
|
print(bell)
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Want to send 00")
|
||||||
|
_00 = I.on(bell[0])
|
||||||
|
print(_00)
|
||||||
|
print()
|
||||||
|
print("Want to send 01")
|
||||||
|
_01 = X.on(bell[0])
|
||||||
|
print(_01)
|
||||||
|
print()
|
||||||
|
print("Want to send 10")
|
||||||
|
_10 = Z.on(bell[0])
|
||||||
|
print(_10)
|
||||||
|
print()
|
||||||
|
print("Want to send 11")
|
||||||
|
_11 = X.on(Z.on(bell[0])[0])
|
||||||
|
print(_11)
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Bob measures...")
|
||||||
|
print("00")
|
||||||
|
m00 = H.on(CNOT.on(_00)[0])
|
||||||
|
print(m00)
|
||||||
|
print()
|
||||||
|
print("01")
|
||||||
|
m01 = H.on(CNOT.on(_01)[0])
|
||||||
|
print(m01)
|
||||||
|
print()
|
||||||
|
print("10")
|
||||||
|
m10 = H.on(CNOT.on(_10)[0])
|
||||||
|
print(m10)
|
||||||
|
print()
|
||||||
|
print("11")
|
||||||
|
m11 = H.on(CNOT.on(_11)[0])
|
||||||
|
print(m11)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
quantum_dense_coding()
|
@ -1,44 +1,101 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
__0 = [[1],
|
||||||
|
[0]]
|
||||||
|
|
||||||
|
__1 = [[0],
|
||||||
|
[1]]
|
||||||
|
|
||||||
|
_I = [
|
||||||
|
[1, 0],
|
||||||
|
[0, 1],
|
||||||
|
]
|
||||||
|
|
||||||
|
_X = [
|
||||||
|
[0, 1],
|
||||||
|
[1, 0],
|
||||||
|
]
|
||||||
|
|
||||||
|
_Y = [
|
||||||
|
[0, complex(0, -1)],
|
||||||
|
[complex(0, 1), 0],
|
||||||
|
]
|
||||||
|
|
||||||
|
_Z = [
|
||||||
|
[1, 0],
|
||||||
|
[0, -1],
|
||||||
|
]
|
||||||
|
|
||||||
|
_H = [
|
||||||
|
[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
||||||
|
[1 / np.sqrt(2), -1 / np.sqrt(2)]
|
||||||
|
]
|
||||||
|
|
||||||
|
_CNOT = [
|
||||||
|
[1, 0, 0, 0],
|
||||||
|
[0, 1, 0, 0],
|
||||||
|
[0, 0, 0, 1],
|
||||||
|
[0, 0, 1, 0],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class State(object):
|
class State(object):
|
||||||
def __init__(self, matrix_state):
|
def __init__(self, matrix_state):
|
||||||
self._matrix_state = matrix_state
|
self.matrix_state = np.array(matrix_state)
|
||||||
|
|
||||||
|
def __getitem__(self, item):
|
||||||
|
if item >= len(self):
|
||||||
|
raise IndexError
|
||||||
|
self.item = item
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return int(np.log2(self.matrix_state.shape[0]))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self._matrix_state)
|
return str(self.matrix_state)
|
||||||
|
|
||||||
|
|
||||||
|
def kron(_list):
|
||||||
|
"""Calculates a Kronicker product of a list of matrices
|
||||||
|
This is essentially a np.kron(*args) since np.kron takes (a,b)"""
|
||||||
|
if type(_list) != list or len(_list) <= 1:
|
||||||
|
return np.array([])
|
||||||
|
rv = np.array(_list[0])
|
||||||
|
for item in _list[1:]:
|
||||||
|
rv = np.kron(rv, item)
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
class Gate(State):
|
class Gate(State):
|
||||||
def on(self, state, q2=None):
|
def on(self, state):
|
||||||
this = self._matrix_state
|
"""
|
||||||
a = state._matrix_state
|
Applies
|
||||||
if q2:
|
:param state: another state (e.g. H(q1) or a list of states (e.g. for CNOT([q1, q2]))
|
||||||
a = np.kron(a, q2._matrix_state)
|
:return:
|
||||||
return State(this.dot(a))
|
"""
|
||||||
|
this_state = self.matrix_state
|
||||||
|
if type(state) == list:
|
||||||
|
other_state = kron([e.matrix_state for e in state])
|
||||||
|
else:
|
||||||
|
other_state = state.matrix_state
|
||||||
|
if this_state.shape[1] != other_state.shape[0]:
|
||||||
|
# The two arrays are different sizes
|
||||||
|
# Use the Kronicker product of Identity with the state.item
|
||||||
|
larger_side = max(this_state.shape[1], this_state.shape[0])
|
||||||
|
_list = [this_state if i == state.item else _I for i in range(larger_side)]
|
||||||
|
this_state = kron(_list)
|
||||||
|
return State(this_state.dot(other_state))
|
||||||
|
|
||||||
|
|
||||||
class Qubit(State): ...
|
class Qubit(State): ...
|
||||||
|
|
||||||
|
|
||||||
_0 = np.array([[1],
|
# List of gates
|
||||||
[0]])
|
I = Gate(_I)
|
||||||
|
X = Gate(_X)
|
||||||
|
Y = Gate(_Y)
|
||||||
|
Z = Gate(_Z)
|
||||||
|
H = Gate(_H)
|
||||||
|
|
||||||
H = Gate(np.array([
|
CNOT = Gate(_CNOT)
|
||||||
[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
|
||||||
[1 / np.sqrt(2), -1 / np.sqrt(2)]
|
|
||||||
]))
|
|
||||||
|
|
||||||
CNOT = Gate(np.array([
|
|
||||||
[1, 0, 0, 0],
|
|
||||||
[0, 1, 0, 0],
|
|
||||||
[0, 0, 0, 1],
|
|
||||||
[0, 0, 1, 0],
|
|
||||||
]))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# E.g. Bell state
|
|
||||||
q1 = Qubit(_0)
|
|
||||||
q2 = Qubit(_0)
|
|
||||||
bell = CNOT.on(H.on(q1), q2)
|
|
||||||
print(bell)
|
|
||||||
|
71
lib_q_computer_old.py
Normal file
71
lib_q_computer_old.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""
|
||||||
|
TODO: DEPRECATE THIS ONE IN FAVOR OF lib_q_computer.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# |0> and |1>
|
||||||
|
_0 = np.array([[1],
|
||||||
|
[0]])
|
||||||
|
_1 = np.array([[0],
|
||||||
|
[1]])
|
||||||
|
|
||||||
|
# |+> and |->
|
||||||
|
_p = np.array([[1 / np.sqrt(2)],
|
||||||
|
[1 / np.sqrt(2)]])
|
||||||
|
_m = np.array([[1 / np.sqrt(2)],
|
||||||
|
[-1 / np.sqrt(2)]])
|
||||||
|
|
||||||
|
# Gates - Identity, Pauli X and Hadamard
|
||||||
|
I = np.array([[1, 0],
|
||||||
|
[0, 1]])
|
||||||
|
X = np.array([[0, 1],
|
||||||
|
[1, 0]])
|
||||||
|
H = np.array([[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
||||||
|
[1 / np.sqrt(2), -1 / np.sqrt(2)]])
|
||||||
|
|
||||||
|
|
||||||
|
def measure_probability(qbit):
|
||||||
|
"""
|
||||||
|
In a qbit [a, b] normalized: |a|^2 + |b|^2 = 1
|
||||||
|
Probability of 0 is |a|^2 and 1 with prob |b|^2
|
||||||
|
|
||||||
|
:returns: tuple of probabilities to measure 0 or 1"""
|
||||||
|
return np.abs(qbit[0][0]) ** 2, np.abs(qbit[1][0]) ** 2
|
||||||
|
|
||||||
|
|
||||||
|
def measure(qbit):
|
||||||
|
"""
|
||||||
|
This gets a random choice of either 0 and 1 with weights
|
||||||
|
based on the probabilities of the qbit
|
||||||
|
|
||||||
|
:returns: classical bit based on qbit probabilities"""
|
||||||
|
return random.choices([0, 1], measure_probability(qbit))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def run_qbit_tests():
|
||||||
|
# asserts are sets of tests to check if mathz workz
|
||||||
|
|
||||||
|
# Identity: verify that I|0> == |0> and I|1> == |0>
|
||||||
|
assert np.array_equal(I.dot(_0), _0)
|
||||||
|
assert np.array_equal(I.dot(_1), _1)
|
||||||
|
|
||||||
|
# Pauli X: verify that X|0> == |1> and X|1> == |0>
|
||||||
|
assert np.array_equal(X.dot(_0), _1)
|
||||||
|
assert np.array_equal(X.dot(_1), _0)
|
||||||
|
|
||||||
|
# measure probabilities in sigma_x of |0> and |1>
|
||||||
|
# using allclose since dealing with floats
|
||||||
|
assert np.allclose(measure_probability(_0), (1.0, 0.0))
|
||||||
|
assert np.allclose(measure_probability(_1), (0.0, 1.0))
|
||||||
|
|
||||||
|
# applying Hadamard puts the qbit in orthogonal +/- basis
|
||||||
|
assert np.array_equal(H.dot(_0), _p)
|
||||||
|
assert np.array_equal(H.dot(_1), _m)
|
||||||
|
|
||||||
|
# measure probabilities in sigma_x of |+> and |->
|
||||||
|
# using allclose since dealing with floats
|
||||||
|
assert np.allclose(measure_probability(_p), (0.5, 0.5))
|
||||||
|
assert np.allclose(measure_probability(_m), (0.5, 0.5))
|
Loading…
Reference in New Issue
Block a user