-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathllistsparsematrix.py
234 lines (193 loc) · 7.82 KB
/
llistsparsematrix.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
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# Implementation of the Sparse Matrix ADT using an array of linked lists.
from myarray import myArray
class SparseMatrix:
# Creates a sparse matrix of size numRows * numCols initialized to 0
def __init__( self, numRows, numCols ):
self._numCols = numCols
self._listOfRows = myArray( numRows )
# Returns the number of rows in the matrix.
def numRows( self ):
return len( self._listOfRows )
# Returns the number of columns in the matrix.
def numCols( self ):
return self._numCols
# Returns the value of element (i,j): x[i, j]
def __getitem__( self, ndxTuple ):
row = ndxTuple[0]
col = ndxTuple[1]
assert row >= 0 and row < self.numRows() and col >= 0 and col < self.numCols(),\
"subsripts out of range"
curNode = self._listOfRows[row]
while curNode is not None and curNode.col != col:
curNode = curNode.next
if curNode:
return curNode.value
else:
return 0
# Sets the value of element (i, j) to the value s: x[i, j] = s
def __setitem__( self, ndxTuple, value ):
row = ndxTuple[0]
col = ndxTuple[1]
assert row >= 0 and row < self.numRows() and col >= 0 and col < self.numCols(),\
"subsripts out of range"
preNode = None
curNode = self._listOfRows[row]
while curNode is not None and curNode.col != col:
preNode = curNode
curNode = curNode.next
# See if the element is in the list.
if curNode is not None and curNode.col == col:
if value == 0.0: # remove the node
if curNode == self._listOfRows[row]:
self._listOfRows[row] = curNode.next
else:
preNode.next = curNode.next
else: # change the node's value.
curNode.value = value
# Otherwise, the element is not in the list
elif value != 0.0:
newNode = _MatrixElementNode( col, value )
newNode.next = curNode
if curNode == self._listOfRows[row]:
self._listOfRows[row] = newNode
else:
preNode.next = newNode
# Scales the matrix by the given scalar
def scaleBy( self, scalar ):
for row in range( self.numRows() ):
curNode = self._listOfRows[row]
while curNode is not None:
self[row, curNode.col] = curNode.value * scalar
curNode = curNode.next
# Creates and returns a new matrix that is the transpose of this matrix.
def transpose( self ):
newMatrix = SparseMatrix( self.numCols(), self.numRows() )
for row in range( self.numRows() ):
curNode = self._listOfRows[row]
while curNode is not None:
newMatrix[curNode.col, row] = curNode.value
curNode = curNode.next
return newMatrix
# Matrix addition: newMatrix = self + rhsMatrix.
def __add__( self, rhsMatrix ):
# Make sure the two matrices have the correct size.
assert rhsMatrix.numRows() == self.numRows() and \
rhsMatrix.numCols() == self.numCols(), \
"Matrix sizes not compatable for adding."
# Create a new sparse matrix of the same size.
newMatrix = SparseMatrix( self.numRows(), self.numCols() )
# Duplicate the element of this matrix to the new matrix.
for row in range( self.numRows() ):
curNode = self._listOfRows[row]
while curNode is not None:
newMatrix[row, curNode.col] = curNode.value
curNode = curNode.next
# Add the elements of the rhsMatrix to the new matrix.
for row in range( rhsMatrix.numRows() ):
curNode = rhsMatrix._listOfRows[row]
while curNode is not None:
value = newMatrix[row, curNode.col]
value += curNode.value
newMatrix[row, curNode.col] = value
curNode = curNode.next
return newMatrix
# Matrix subtraction: newMatrix = self - rhsMatrix
def __sub__( self, rhsMatrix ):
# Make sure the two matrices have the correct size.
assert rhsMatrix.numRows() == self.numRows() and \
rhsMatrix.numCols() == self.numCols(), \
"Matrix sizes not compatable for subtract."
# Create a new sparse matrix of the same size.
newMatrix = SparseMatrix( self.numRows(), self.numCols() )
# Duplicate the element of this matrix to the new matrix.
for row in range( self.numRows() ):
curNode = self._listOfRows[row]
while curNode is not None:
newMatrix[row, curNode.col] = curNode.value
curNode = curNode.next
# Sub the elements of the rhsMatrix to the new matrix.
for row in range( rhsMatrix.numRows() ):
curNode = rhsMatrix._listOfRows[row]
while curNode is not None:
value = newMatrix[row, curNode.col]
value -= curNode.value
newMatrix[row, curNode.col] = value
curNode = curNode.next
return newMatrix
# Matrix multiplication: newMatrix = self * rhsMatrix
def __mul__( self, rhsMatrix ):
assert rhsMatrix.numRows() == self.numCols(), \
"Marix sizes not compatible for the multiply operation."
# Create the new matrix
newMatrix = SparseMatrix( self.numRows(), rhsMatrix.numCols() )
for row in range( self.numRows() ):
for col in range( rhsMatrix.numCols() ):
tmp_sum = 0
for kk in range( self.numCols() ):
if self[ row, kk ] != 0 and rhsMatrix[ kk, col ] != 0:
tmp_sum += self[ row, kk ] * rhsMatrix[ kk, col ]
newMatrix[ row, col ] = tmp_sum
return newMatrix
# Storage class for creating matrix element nodes.
class _MatrixElementNode:
def __init__( self, col, value ):
self.col = col
self.value = value
self.next = None
if __name__ == '__main__':
sparse_mat_A = SparseMatrix( 3, 4 )
sparse_mat_B = SparseMatrix( 3, 4 )
sparse_mat_C = SparseMatrix( 4, 2 )
sparse_mat_A[0, 0] = 1
sparse_mat_A[2, 3] = 3
sparse_mat_B[1, 2] = 4
sparse_mat_B[2, 3] = -3
sparse_mat_B[2, 2] = 1
sparse_mat_C[0, 0] = 5
sparse_mat_C[2, 1] = 2
sparse_mat_C[3, 1] = 11
print 'mat A: '
for i in range(3):
for j in range(4):
print sparse_mat_A[i, j],
print ''
print 'mat B: '
for i in range(3):
for j in range(4):
print sparse_mat_B[i, j],
print ''
print 'mat C: '
for i in range(4):
for j in range(2):
print sparse_mat_C[i, j],
print ''
add_mat_01 = sparse_mat_A + sparse_mat_B
print 'A + B: '
for i in range( add_mat_01.numRows() ):
for j in range( add_mat_01.numCols() ):
print add_mat_01[i, j],
print ''
sub_mat_02 = sparse_mat_A - sparse_mat_B
print 'A - B: '
for i in range( sub_mat_02.numRows() ):
for j in range( sub_mat_02.numCols() ):
print sub_mat_02[i, j],
print ''
mul_mat_03 = sparse_mat_A * sparse_mat_C
print 'A * C: '
for i in range( mul_mat_03.numRows() ):
for j in range( mul_mat_03.numCols() ):
print mul_mat_03[i, j],
print ''
transpos_mat = sparse_mat_A.transpose()
print 'A.T: '
for i in range( transpos_mat.numRows() ):
for j in range( transpos_mat.numCols() ):
print transpos_mat[i, j],
print ''
sparse_mat_B.scaleBy(3)
print 'B * 3: '
for i in range( sparse_mat_B.numRows() ):
for j in range( sparse_mat_B.numCols() ):
print sparse_mat_B[i, j],
print ''