source: inundation/ga/storm_surge/pyvolution/sparse.py @ 471

Last change on this file since 471 was 471, checked in by ole, 20 years ago
File size: 4.9 KB
Line 
1"""Proof of concept sparse matrix code
2"""
3
4#from scipy_base import * #Hardly worth importing scipy just to get isscalar.
5from cg_solve import conjugate_gradient, VectorShapeError
6
7class Sparse:
8
9    def __init__(self, M, N):
10        """Set dimensions
11        """
12
13        self.M = M
14        self.N = N
15        self.shape = (M,N)
16        self.A = {}
17
18    def __repr__(self):
19        return '%d X %d sparse matrix:\n' %(self.M, self.N) + `self.A` 
20
21    def __setitem__(self, key, x):
22
23        i,j = key
24        assert 0 <= i < self.M
25        assert 0 <= j < self.N       
26
27        if x != 0:
28            self.A[key] = float(x)
29        else:
30            if self.A.has_key( key ):           
31                del self.A[key]
32
33    def __getitem__(self, key):
34       
35        i,j = key
36        assert 0 <= i < self.M
37        assert 0 <= j < self.N               
38
39        if self.A.has_key( key ):
40            return self.A[ key ]
41        else:
42            return 0.0
43
44    def copy(self):
45
46        new = Sparse(self.M,self.N)
47
48        for key in self.A.keys():
49            i, j = key
50
51            new[i,j] = self.A[i,j]
52
53        return new
54
55
56    def todense(self):
57        from Numeric import zeros, Float
58
59        D = zeros( (self.M, self.N), Float)
60       
61        for i in range(self.M):
62            for j in range(self.N):
63                if self.A.has_key( (i,j) ):               
64                    D[i, j] = self.A[ (i,j) ]
65        return D
66
67
68    def __mul__(self, other):
69        """Multiply this matrix onto 'other' which can either be
70        a Numeric vector, a Numeric matrix or another sparse matrix.
71        """
72
73        from Numeric import array, zeros, Float
74       
75        try:
76            B = array(other)
77        except:
78            print 'FIXME: Only Numeric types implemented so far'
79
80
81        #Assume numeric types from now on
82        R = zeros((self.M,), Float) #Result
83       
84        if len(B.shape) == 1:
85            #Vector
86
87##             print 'B.shape      ',B.shape
88##             print 'self.shape ',self.shape
89           
90            assert B.shape[0] == self.N, 'Mismatching dimensions'
91
92            #Multiply nonzero elements
93            for key in self.A.keys():
94                i, j = key
95
96                R[i] += self.A[key]*B[j]
97
98        else:
99            raise ValueError, 'Numeric matrix not yet implemented'
100
101        return R
102
103    def __add__(self, other):
104        """Add this matrix onto 'other'
105        """
106
107        from Numeric import array, zeros, Float
108       
109        new = other.copy()
110
111 #       print 'self.shape',self.shape
112 #       print 'other.shape',other.shape
113       
114        for key in self.A.keys():
115            i, j = key
116
117            new[i,j] = new[i,j] + self.A[key]
118
119        return new
120
121
122    def __rmul__(self, other):
123        """Right multiply this matrix with scalar
124        """
125
126        from Numeric import array, zeros, Float
127       
128        try:
129            other = float(other)
130        except:
131            raise 'only right multiple with scalar implemented'
132        else:
133            new = self.copy()
134            #Multiply nonzero elements
135            for key in new.A.keys():
136                i, j = key
137
138                new.A[key] = other*new.A[key]
139
140        return new
141
142
143    def trans_mult(self, other):
144        """Multiply the transpose of  matrix with 'other' which can be
145        a Numeric vector.
146        """
147
148        from Numeric import array, zeros, Float
149       
150        try:
151            B = array(other)
152        except:
153            print 'FIXME: Only Numeric types implemented so far'
154
155
156        #Assume numeric types from now on
157
158       
159        if len(B.shape) == 1:
160            #Vector
161
162            assert B.shape[0] == self.M, 'Mismatching dimensions'
163
164            R = zeros((self.N,), Float) #Result
165
166            #Multiply nonzero elements
167            for key in self.A.keys():
168                i, j = key
169
170                R[j] += self.A[key]*B[i]
171
172        else:
173            raise 'Can only multiply with 1d array'
174
175        return R
176
177
178   
179   
180if __name__ == '__main__':
181
182    from Numeric import allclose, array, Float
183   
184    A = Sparse(3,3)
185
186    A[1,1] = 4
187
188
189    print A
190    print A.todense()
191
192    A[1,1] = 0
193
194    print A
195    print A.todense()   
196
197    A[1,2] = 0
198
199
200    A[0,0] = 3
201    A[1,1] = 2
202    A[1,2] = 2
203    A[2,2] = 1
204
205    print A
206    print A.todense()
207
208
209    #Right hand side vector
210    v = [2,3,4]
211
212    u = A*v
213    print u
214    assert allclose(u, [6,14,4])
215
216    u = A.trans_mult(v)
217    print u
218    assert allclose(u, [6,6,10])
219
220    #Right hand side column
221    v = array([[2,4],[3,4],[4,4]])
222
223    u = A*v[:,0]
224    assert allclose(u, [6,14,4])
225
226    #u = A*v[:,1]
227    #print u
228    print A.shape
229
230    B = 3*A
231    print B.todense()
232
233    B[1,0] = 2
234
235    C = A+B
236
237    print C.todense()
Note: See TracBrowser for help on using the repository browser.