-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatrix.py
More file actions
209 lines (166 loc) · 6.22 KB
/
Copy pathmatrix.py
File metadata and controls
209 lines (166 loc) · 6.22 KB
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
class Matrix:
def __init__(self, data):
if not data or not data[0]:
raise ValueError("빈 행렬은 생성할 수 없습니다")
self.data = [row[:] for row in data]
self.rows = len(data)
self.cols = len(data[0])
@classmethod
def zeros(cls, rows, cols):
return cls([[0] * cols for _ in range(rows)])
@classmethod
def ones(cls, rows, cols):
return cls([[1] * cols for _ in range(rows)])
@classmethod
def identity(cls, n):
data = [[1 if i == j else 0 for j in range(n)] for i in range(n)]
return cls(data)
@classmethod
def from_flat(cls, flat_list, rows, cols):
if len(flat_list) != rows * cols:
raise ValueError("크기가 맞지 않습니다")
data = [flat_list[i * cols : (i + 1) * cols] for i in range(rows)]
return cls(data)
def __getitem__(self, key):
if isinstance(key, tuple):
return self.data[key[0]][key[1]]
return self.data[key]
def __setitem__(self, key, value):
if isinstance(key, tuple):
self.data[key[0]][key[1]] = value
else:
self.data[key] = value
def __add__(self, other):
if self.rows != other.rows or self.cols != other.cols:
raise ValueError("행렬 크기가 다릅니다")
result = [
[self.data[i][j] + other.data[i][j] for j in range(self.cols)]
for i in range(self.rows)
]
return Matrix(result)
def __sub__(self, other):
if self.rows != other.rows or self.cols != other.cols:
raise ValueError("행렬 크기가 다릅니다")
result = [
[self.data[i][j] - other.data[i][j] for j in range(self.cols)]
for i in range(self.rows)
]
return Matrix(result)
def __mul__(self, other):
if isinstance(other, (int, float)):
result = [
[self.data[i][j] * other for j in range(self.cols)]
for i in range(self.rows)
]
return Matrix(result)
if self.cols != other.rows:
raise ValueError(
f"행렬 곱셈 불가: ({self.rows}x{self.cols}) * ({other.rows}x{other.cols})"
)
result = [
[
sum(self.data[i][k] * other.data[k][j] for k in range(self.cols))
for j in range(other.cols)
]
for i in range(self.rows)
]
return Matrix(result)
def transpose(self):
result = [
[self.data[j][i] for j in range(self.rows)] for i in range(self.cols)
]
return Matrix(result)
def determinant(self):
if self.rows != self.cols:
raise ValueError("정방행렬이 아닙니다")
if self.rows == 1:
return self.data[0][0]
if self.rows == 2:
return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]
det = 0
for j in range(self.cols):
minor = self._minor(0, j)
cofactor = ((-1) ** j) * self.data[0][j] * minor.determinant()
det += cofactor
return det
def _minor(self, row, col):
data = [
[self.data[i][j] for j in range(self.cols) if j != col]
for i in range(self.rows)
if i != row
]
return Matrix(data)
def trace(self):
if self.rows != self.cols:
raise ValueError("정방행렬이 아닙니다")
return sum(self.data[i][i] for i in range(self.rows))
def flatten(self):
return [x for row in self.data for x in row]
def map(self, func):
result = [[func(self.data[i][j]) for j in range(self.cols)] for i in range(self.rows)]
return Matrix(result)
def row_echelon(self):
mat = [row[:] for row in self.data]
rows, cols = self.rows, self.cols
current_row = 0
for col in range(cols):
max_row = current_row
for row in range(current_row + 1, rows):
if abs(mat[row][col]) > abs(mat[max_row][col]):
max_row = row
if abs(mat[max_row][col]) < 1e-10:
continue
mat[current_row], mat[max_row] = mat[max_row], mat[current_row]
pivot = mat[current_row][col]
mat[current_row] = [x / pivot for x in mat[current_row]]
for row in range(current_row + 1, rows):
factor = mat[row][col]
mat[row] = [
mat[row][j] - factor * mat[current_row][j] for j in range(cols)
]
current_row += 1
return Matrix(mat)
def __eq__(self, other):
return self.data == other.data
def __repr__(self):
rows_str = []
for row in self.data:
rows_str.append(" [" + ", ".join(f"{x:>6.2f}" for x in row) + "]")
return "Matrix([\n" + "\n".join(rows_str) + "\n])"
def pretty_print(self):
col_widths = []
for j in range(self.cols):
width = max(len(f"{self.data[i][j]:.2f}") for i in range(self.rows))
col_widths.append(width)
for i in range(self.rows):
row_str = " | ".join(
f"{self.data[i][j]:>{col_widths[j]}.2f}" for j in range(self.cols)
)
print(f"| {row_str} |")
if __name__ == "__main__":
print("=== 기본 연산 ===")
a = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b = Matrix([[9, 8, 7], [6, 5, 4], [3, 2, 1]])
print("A:")
a.pretty_print()
print("\nB:")
b.pretty_print()
print("\nA + B:")
(a + b).pretty_print()
print("\nA * B:")
(a * b).pretty_print()
print(f"\nA 전치:")
a.transpose().pretty_print()
print(f"\n대각합: {a.trace()}")
print("\n=== 단위행렬 ===")
Matrix.identity(4).pretty_print()
print("\n=== 행렬식 ===")
m = Matrix([[1, 2], [3, 4]])
print(f"det([[1,2],[3,4]]) = {m.determinant()}")
m3 = Matrix([[2, 1, 3], [0, -1, 2], [1, 4, -1]])
print(f"det(3x3) = {m3.determinant()}")
print("\n=== 스칼라 곱 ===")
(m * 3).pretty_print()
print("\n=== Row Echelon ===")
m4 = Matrix([[2, 1, -1, 8], [-3, -1, 2, -11], [-2, 1, 2, -3]])
m4.row_echelon().pretty_print()