forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsparsemat.py
More file actions
74 lines (66 loc) · 2.55 KB
/
sparsemat.py
File metadata and controls
74 lines (66 loc) · 2.55 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
from __future__ import division
EPSILON = 1E-12
class SparseMatrix:
def __init__(self, height):
self.lines = [{} for row in range(height)]
def __getitem__(self, (row, col)):
return self.lines[row].get(col, 0)
def __setitem__(self, (row, col), value):
if abs(value) > EPSILON:
self.lines[row][col] = value
else:
try:
del self.lines[row][col]
except KeyError:
pass
def copy(self):
m = SparseMatrix(len(self.lines))
for line1, line2 in zip(self.lines, m.lines):
line2.update(line1)
return m
def solve(self, vector):
"""Solves 'self * [x1...xn] == vector'; returns the list [x1...xn].
Raises ValueError if no solution or indeterminate.
"""
vector = list(vector)
lines = [line.copy() for line in self.lines]
columns = [{} for i in range(len(vector))]
for i, line in enumerate(lines):
for j, a in line.items():
columns[j][i] = a
lines_left = dict.fromkeys(range(len(self.lines)))
nrows = []
for ncol in range(len(vector)):
currentcolumn = columns[ncol]
lst = [(abs(a), i) for (i, a) in currentcolumn.items()
if i in lines_left]
_, nrow = max(lst) # ValueError -> no solution
nrows.append(nrow)
del lines_left[nrow]
line1 = lines[nrow]
maxa = line1[ncol]
for _, i in lst:
if i != nrow:
line2 = lines[i]
a = line2.pop(ncol)
#del currentcolumn[i] -- but currentcolumn no longer used
factor = a / maxa
vector[i] -= factor*vector[nrow]
for col in line1:
if col > ncol:
value = line2.get(col, 0) - factor*line1[col]
if abs(value) > EPSILON:
line2[col] = columns[col][i] = value
else:
line2.pop(col, 0)
columns[col].pop(i, 0)
solution = [None] * len(vector)
for i in range(len(vector)-1, -1, -1):
row = nrows[i]
line = lines[row]
total = vector[row]
for j, a in line.items():
if j != i:
total -= a * solution[j]
solution[i] = total / line[i]
return solution