-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmatrix.py
165 lines (144 loc) · 5.33 KB
/
matrix.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
class Matrix: # A python implementation of Matrices
def __init__(self, lst, dtype=float):
assert isinstance(lst, list) and isinstance(lst[0], list)
self.row = len(lst)
self.col = len(lst[0])
self.dtype = dtype
self._matrix = [[dtype(lst[i][j]) for j in range(self.col)] for i in range(self.row)]
@classmethod
def construct(cls, row, col, fill=0, dtype=float):
lst = [[fill for j in range(col)] for i in range(row)]
return cls(lst, dtype=dtype)
@classmethod
def identity(cls, rank, dtype=float):
lst = [[1 if i == j else 0 for j in range(rank)] for i in range(rank)]
return cls(lst, dtype=dtype)
@property
def shape(self):
return (self.row, self.col)
@property
def issquare(self):
return self.row == self.col
def copy(self):
res = self.construct(self.row, self.col, dtype=self.dtype)
for i in range(self.row):
for j in range(self.col):
res[i, j] = self[i, j]
return res
def __repr__(self):
res = str()
if self.dtype == float:
rep = lambda x:str(round(x+1e-10, 6))
else:
rep = str
res = '[ ' + '\n '.join([' '.join(list(map(rep, row))) for row in self._matrix]) + ' ]'
return res
def __getitem__(self, index):
return self._matrix[index[0]][index[1]]
def __setitem__(self, index, value):
assert isinstance(value, self.dtype)
self._matrix[index[0]][index[1]] = value
def __add__(self, obj):
assert isinstance(obj, Matrix) and self.shape == obj.shape
res = self.construct(self.row, self.col, dtype=self.dtype)
for i in range(self.row):
for j in range(self.col):
res[i, j] = self[i, j] + obj[i, j]
return res
def __sub__(self, obj):
assert isinstance(obj, Matrix) and self.shape == obj.shape
res = self.construct(self.row, self.col, dtype=self.dtype)
for i in range(self.row):
for j in range(self.col):
res[i, j] = self[i, j] - obj[i, j]
return res
def __mul__(self, obj):
if isinstance(obj, self.dtype):
res = self.construct(self.row, self.col, dtype=self.dtype)
for i in range(self.row):
for j in range(self.col):
res[i, j] = self[i, j] * obj
return res
else:
assert isinstance(obj, Matrix) and self.col == obj.row
res = self.construct(self.row, obj.col, dtype=self.dtype)
for i in range(self.row):
for j in range(obj.col):
temp = self.dtype(0)
for k in range(self.col):
temp += self[i, k] * obj[k, j]
res[i, j] = temp
return res
def __truediv__(self, obj):
assert isinstance(obj, Matrix) and self.col == obj.row and obj.issquare
return self.__mul__(obj.inv())
def __pow__(self, obj):
assert isinstance(obj, int) and self.issquare and obj >= -1
if obj == -1:
return self.inv()
res = self.identity(self.row, dtype=self.dtype)
temp = self.copy()
while obj:
if obj & 1:
res = res * temp
temp = temp * temp
obj >>= 1
return res
def __eq__(self, obj):
assert isinstance(obj, Matrix) and obj.shape == self.shape
for i in range(self.row):
for j in range(self.col):
if not self[i, j] == obj[i, j]:
return False
return True
def transpose(self):
res = self.construct(self.col, self.row, dtype=self.dtype)
for i in range(self.col):
for j in range(self.row):
res[i, j] = self[j, i]
return res
def _cofactor_matrix(self, row, col):
assert self.row > 1 and row <= self.row and col <= self.col
res = self.construct(self.row-1, self.col-1, dtype=self.dtype)
for i in range(self.row):
if i == row:
continue
for j in range(self.col):
if j == col:
continue
ii = i-1 if i > row else i
jj = j-1 if j > col else j
res[ii, jj] = self[i, j]
return res
def alg_cofactor(self, row, col):
assert self.issquare
return (self.dtype(-1)**(row+col)) * self._cofactor_matrix(row, col).det()
def det(self):
assert self.issquare
if self.row == 1:
return self[0, 0]
res = self.dtype(0)
for i in range(self.row):
res += self[0, i] * self.alg_cofactor(0, i)
return res
def inv(self):
assert self.issquare
det = self.det()
res = self.construct(self.row, self.col, dtype=self.dtype)
for i in range(self.row):
for j in range(self.col):
res[i, j] = self.alg_cofactor(j, i) / det
return res
if __name__ == '__main__':
A = Matrix([[1, 2, 5], [2, 1, -9], [8, 9, 1]])
B = Matrix([[3, 3, 7], [4, 1, 0], [-8, 4, 3]])
print(A)
print(B)
print(A+B)
print(A-B)
print(A-A)
print(A*B)
print(A/B)
print(A/A)
print(A**3)
print(A**-1)