quantum/lib_q_computer.py

117 lines
2.8 KiB
Python
Raw Normal View History

2019-12-04 10:08:37 +01:00
import numpy as np
2019-12-04 17:26:41 +01:00
# Raw matrixes to be used for initialization of qubits and gates
2019-12-04 17:17:36 +01:00
__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],
]
2019-12-04 10:08:37 +01:00
class State(object):
2019-12-04 17:26:41 +01:00
"""Represents a quantum state"""
2019-12-04 10:08:37 +01:00
def __init__(self, matrix_state):
2019-12-04 17:26:41 +01:00
"""
Can be initialized with a matrix, e.g. for |0> this is [[0],[1]]
:param matrix_state: a matrix representing the quantum state
"""
2019-12-04 17:17:36 +01:00
self.matrix_state = np.array(matrix_state)
def __getitem__(self, item):
2019-12-04 17:26:41 +01:00
"""
Kind of hacky way to store a substate of an item for use in Gate operations
so that one can use state[0] and the encompassing operator can access this.
:param item:
:return:
"""
2019-12-04 17:17:36 +01:00
if item >= len(self):
raise IndexError
self.item = item
return self
def __len__(self):
return int(np.log2(self.matrix_state.shape[0]))
2019-12-04 10:08:37 +01:00
def __repr__(self):
2019-12-04 17:17:36 +01:00
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
2019-12-04 10:08:37 +01:00
class Gate(State):
2019-12-04 17:17:36 +01:00
def on(self, state):
"""
2019-12-04 17:26:41 +01:00
Applies a gate operation on a state.
If applying to a substate, use the index of the substate, e.g. `H.on(bell[0])` will apply the Hadamard gate
on the 0th qubit of the `bell` state.
:param state: another state (e.g. `H.on(q1)` or a list of states (e.g. for `CNOT.on([q1, q2])`)
:return: the state after the application of the Gate
2019-12-04 17:17:36 +01:00
"""
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
2019-12-04 17:26:41 +01:00
# Use the Kronicker product of Identity with the state.item where
# state.item is the substate
2019-12-04 17:17:36 +01:00
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))
2019-12-04 10:08:37 +01:00
class Qubit(State): ...
2019-12-04 17:17:36 +01:00
# List of gates
I = Gate(_I)
X = Gate(_X)
Y = Gate(_Y)
Z = Gate(_Z)
H = Gate(_H)
2019-12-04 10:08:37 +01:00
2019-12-04 17:17:36 +01:00
CNOT = Gate(_CNOT)