-
Notifications
You must be signed in to change notification settings - Fork 0
/
program.py
126 lines (109 loc) · 4.03 KB
/
program.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import numpy as np
#define matrices for standard gates
X = np.array([[0.0,1.0],[1.0,0.0]])
Y = np.array([[0,-1.0j],[1.0j,0.0]])
Z = np.array([[1.0,0.0],[0.0,-1.0]])
I = np.eye(2)
H = np.array([[1.0,1.0],[1.0,-1.0]])*(1/np.sqrt(2.0))
CNOT = np.array([[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,0.0,1.0],[0.0,0.0,1.0,0.0]])
CZ = np.array([[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[0.0,0.0,0.0,-1.0]])
gate_dict = {
"X": X,
"Y": Y,
"Z": Z,
"I": I,
"H": H,
"CNOT": CNOT,
"CZ": CZ
}
class Gate:
def __init__(self, name, qubits, angles=[]):
self.name = name
self. angles = angles
self.qubits = qubits
def matrix(self):
if self.name in gate_dict:
return gate_dict[self.name]
elif (self.name == 'RZ'):
return np.array([[np.cos(self.angles[0]/2)-1.0j*np.sin(self.angles[0]/2), 0],[0, np.cos(self.angles[0]/2)+1.0j*np.sin(self.angles[0]/2)]])
elif (self.name == 'RX'):
return np.array([[np.cos(self.angles[0]/2), -1.0j*np.sin(self.angles[0]/2)],[-1.0j*np.sin(self.angles[0]/2), np.cos(self.angles[0]/2)]])
elif (self.name == 'RY'):
return np.array([[np.cos(self.angles[0]/2), -np.sin(self.angles[0]/2)],[np.sin(self.angles[0]/2), np.cos(self.angles[0]/2)]])
else:
print("Error: ", self.name, " is not a known gate name!")
exit()
def gate_from_Pauli(self, pauli):
self.name = pauli.name
self.qubits = pauli.qubit
self.angles = []
def print_gate(self):
if (self.angles != []):
print(self.name,"(",self.angles[0],")",self.qubits)
else:
print(self.name,self.qubits)
class Pauli:
def __init__(self, name, qubit):
self.name = name
self.qubit = qubit
class Term:
def __init__(self, paulis, coeff):
self.paulis = paulis
self.coeff = coeff
class Hamiltonian:
def __init__(self, nqubits, terms):
self.nqubits = nqubits
self.terms = terms
def add_term(self, term):
self.term.append(term)
def matrix(self):
dim = 2**self.nqubits
ham_mat = np.zeros((dim,dim))
for term in self.terms:
kron_list = ['I'] * self.nqubits
for pauli in term.paulis:
kron_list[pauli.qubit] = pauli.name
for q in range(self.nqubits-1):
if (q==0):
mat = np.kron(gate_dict[kron_list[0]], gate_dict[kron_list[1]])
else:
mat = np.kron(mat, gate_dict[kron_list[q+1]])
mat = term.coeff * mat
ham_mat = ham_mat + mat
return ham_mat
def show(self):
dim = 2**self.nqubits
ham_mat = self.matrix()
for i in range(dim):
for j in range(dim):
print(ham_mat[i][j])
class Program:
def __init__(self, nqubits):
self.nqubits = nqubits
self.gates = []
def add_instr(self, gate_list):
for gate in gate_list:
self.gates.append(gate)
def get_U(self):
dim = 2**self.nqubits
matU = np.eye(dim)
for gate in self.gates:
#make sure gate matrix has dimension of system
if(self.nqubits > 1):
kron_list = [I] * self.nqubits
kron_list[gate.qubits[0]] = gate.matrix()
num_prods = self.nqubits-1
if (len(gate.qubits) == 2):
num_prods = self.nqubits-2
if (self.nqubits > 2):
#for a 2-qubit gate, the last identity should be removed from kron_list
kron_list.pop()
else: mat = gate.matrix()
for q in range(num_prods):
if (q==0):
mat = np.kron(kron_list[0], kron_list[1])
else:
mat = np.kron(mat, kron_list[q+1])
else: mat = gate_dict[gate.matrix]
matU = np.matmul(matU,mat)
return matU