samer@0
|
1 /*
|
samer@0
|
2 * Matrix.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@0
|
12 package samer.maths;
|
samer@0
|
13 import samer.core.*;
|
samer@0
|
14 import samer.core.util.*;
|
samer@0
|
15 import java.util.*;
|
samer@0
|
16 import java.io.*;
|
samer@0
|
17
|
samer@0
|
18 /**
|
samer@0
|
19 Represents a bundling of a Jama.Matrix with Viewable bits.
|
samer@0
|
20 Create one of these and you can either keep it invisible,
|
samer@0
|
21 expose its UI yourself, or let the Viewable framework
|
samer@0
|
22 expose a default viewer automatically
|
samer@0
|
23 */
|
samer@0
|
24
|
samer@0
|
25 public class Matrix extends Jama.Matrix implements Mat, Saveable
|
samer@0
|
26 {
|
samer@0
|
27 Viewable viewable;
|
samer@0
|
28
|
samer@0
|
29 // ............... Viewable bits .................
|
samer@0
|
30
|
samer@0
|
31 private class Vbl extends Viewable {
|
samer@0
|
32 Vbl(String nm) { super(nm); }
|
samer@0
|
33 Vbl() { super("matrix"); }
|
samer@0
|
34
|
samer@0
|
35 /** returns current Agent if there is one, creates a MatrixAgent if not */
|
samer@0
|
36 public Agent getAgent() {
|
samer@0
|
37 if (super.getAgent()==null) setAgent(new MatrixAgent(Matrix.this));
|
samer@0
|
38 return super.getAgent();
|
samer@0
|
39 }
|
samer@0
|
40
|
samer@0
|
41 public Matrix getMatrix() { return Matrix.this; }
|
samer@0
|
42 public Viewer getViewer()
|
samer@0
|
43 {
|
samer@0
|
44 BaseViewer vwr = new BaseViewer(this);
|
samer@0
|
45 StringBuffer buf = new StringBuffer();
|
samer@0
|
46
|
samer@0
|
47 buf.append(getLabel())
|
samer@0
|
48 .append(" (").append(getRowDimension())
|
samer@0
|
49 .append(" by ").append(getColumnDimension())
|
samer@0
|
50 .append(")");
|
samer@0
|
51 vwr.setText(buf.toString());
|
samer@0
|
52
|
samer@0
|
53 return vwr;
|
samer@0
|
54 }
|
samer@0
|
55 }
|
samer@0
|
56
|
samer@0
|
57 public Observable observable() { return viewable; }
|
samer@0
|
58 public Viewable viewable() { return viewable; }
|
samer@0
|
59 public boolean equals(Observable o) { return viewable==o; }
|
samer@0
|
60 public Node getNode() { return viewable.getNode(); }
|
samer@0
|
61
|
samer@0
|
62 public final void changed(Object o) { viewable.changed(o); }
|
samer@0
|
63 public final void changed() { viewable.changed(); }
|
samer@0
|
64 public void addObserver(Observer o) { viewable.addObserver(o); }
|
samer@0
|
65 public void deleteObserver(Observer o) { viewable.deleteObserver(o); }
|
samer@0
|
66 public void dispose() { viewable.dispose(); }
|
samer@0
|
67
|
samer@0
|
68 public void copyFrom(double[][] src) {
|
samer@0
|
69 double[][] dest=getArray();
|
samer@0
|
70 for (int i=0; i<src.length; i++) {
|
samer@0
|
71 Mathx.copy(src[i],dest[i]);
|
samer@0
|
72 changed();
|
samer@0
|
73 }
|
samer@0
|
74 }
|
samer@0
|
75
|
samer@0
|
76 // ................................................
|
samer@0
|
77
|
samer@0
|
78 public Matrix( String name, int m, int n) { this(name,m,n,1); }
|
samer@0
|
79 public Matrix( String name, int m, int n, int flags) {
|
samer@0
|
80 super(m,n); viewable=new Vbl(name);
|
samer@0
|
81 if (flags==1) Shell.registerViewable(viewable);
|
samer@0
|
82 }
|
samer@0
|
83
|
samer@0
|
84
|
samer@0
|
85 public Matrix( int m, int n) { super(m,n); viewable=new Vbl(); Shell.registerViewable(viewable); }
|
samer@0
|
86 public Matrix( double array[][]) { super(array); viewable=new Vbl(); Shell.registerViewable(viewable); }
|
samer@0
|
87
|
samer@0
|
88 public String toString() {
|
samer@0
|
89 StringBuffer buf = new StringBuffer();
|
samer@0
|
90
|
samer@0
|
91 buf.append(viewable.getLabel())
|
samer@0
|
92 .append(" (").append(getRowDimension())
|
samer@0
|
93 .append(" by ").append(getColumnDimension())
|
samer@0
|
94 .append(")");
|
samer@0
|
95 return buf.toString();
|
samer@0
|
96 }
|
samer@0
|
97
|
samer@0
|
98 // implement Mat interface
|
samer@0
|
99 public int width() { return getColumnDimension(); }
|
samer@0
|
100 public int height() { return getRowDimension(); }
|
samer@0
|
101
|
samer@0
|
102 public Agent getAgent() { return viewable.getAgent(); }
|
samer@0
|
103
|
samer@0
|
104
|
samer@0
|
105 // ................................................
|
samer@0
|
106 // some useful additions to Matrix functionality
|
samer@0
|
107
|
samer@0
|
108 public void set( Generator g) {
|
samer@0
|
109 for (int i=0; i<m; i++) g.next(A[i]);
|
samer@0
|
110 }
|
samer@0
|
111
|
samer@0
|
112 public void apply( Function f) {
|
samer@0
|
113 for (int i=0; i<m; i++) f.apply(A[i]);
|
samer@0
|
114 }
|
samer@0
|
115
|
samer@0
|
116 public void add( Generator g)
|
samer@0
|
117 {
|
samer@0
|
118 for (int i=0; i<m; i++) {
|
samer@0
|
119 for (int j=0; j<n; j++) {
|
samer@0
|
120 A[i][j]+=g.next();
|
samer@0
|
121 }
|
samer@0
|
122 }
|
samer@0
|
123 }
|
samer@0
|
124
|
samer@0
|
125
|
samer@0
|
126 /** Set to identity matrix */
|
samer@0
|
127
|
samer@0
|
128 public void identity()
|
samer@0
|
129 {
|
samer@0
|
130 for (int i = 0; i < m; i++) {
|
samer@0
|
131 for (int j = 0; j < n; j++) {
|
samer@0
|
132 A[i][j] = (i == j ? 1.0 : 0.0);
|
samer@0
|
133 }
|
samer@0
|
134 }
|
samer@0
|
135 }
|
samer@0
|
136
|
samer@0
|
137 public static Jama.Matrix identity(Jama.Matrix a)
|
samer@0
|
138 {
|
samer@0
|
139 double [][] A=a.getArray();
|
samer@0
|
140 int m=a.getRowDimension();
|
samer@0
|
141 int n=a.getColumnDimension();
|
samer@0
|
142 for (int i = 0; i < m; i++) {
|
samer@0
|
143 for (int j = 0; j < n; j++) {
|
samer@0
|
144 A[i][j] = (i == j ? 1.0 : 0.0);
|
samer@0
|
145 }
|
samer@0
|
146 }
|
samer@0
|
147 return a;
|
samer@0
|
148 }
|
samer@0
|
149
|
samer@0
|
150 /** Set to zero matrix */
|
samer@0
|
151
|
samer@0
|
152 public void zero() {
|
samer@0
|
153 for (int i = 0; i < m; i++) { Mathx.zero(A[i]); }
|
samer@0
|
154 }
|
samer@0
|
155
|
samer@0
|
156 /** Set to given matrix
|
samer@0
|
157 * (need to make sure both matrices are the same size)
|
samer@0
|
158 @param b the matrix to be copied
|
samer@0
|
159 */
|
samer@0
|
160
|
samer@0
|
161 public void assign( Jama.Matrix b)
|
samer@0
|
162 {
|
samer@0
|
163 double[][] B=b.getArray();
|
samer@0
|
164 int mmax = B.length>m ? m : B.length;
|
samer@0
|
165 int nmax = B[0].length>n ? n : B[0].length;
|
samer@0
|
166
|
samer@0
|
167 for (int i = 0; i < mmax; i++) {
|
samer@0
|
168 System.arraycopy(B[i],0,A[i],0,nmax);
|
samer@0
|
169 }
|
samer@0
|
170 }
|
samer@0
|
171
|
samer@0
|
172 // Saveable implementation
|
samer@0
|
173
|
samer@0
|
174 public void load(InputStream in) throws Exception {
|
samer@0
|
175 ObjectInputStream o=new ObjectInputStream(in);
|
samer@0
|
176 assign((Jama.Matrix)o.readObject());
|
samer@0
|
177 changed();
|
samer@0
|
178 }
|
samer@0
|
179
|
samer@0
|
180 public void save(OutputStream out) throws Exception {
|
samer@0
|
181 ObjectOutputStream o=new ObjectOutputStream(out);
|
samer@0
|
182 o.writeObject(new Jama.Matrix(getArray()));
|
samer@0
|
183 }
|
samer@0
|
184
|
samer@0
|
185 public void write(Writer wr) throws Exception {
|
samer@0
|
186 print(new PrintWriter(wr,true), new DoubleFormat(16),4);
|
samer@0
|
187 }
|
samer@0
|
188
|
samer@0
|
189 public void read(Reader rdr) throws Exception {
|
samer@0
|
190 Jama.Matrix A=Jama.Matrix.read(new BufferedReader(rdr));
|
samer@0
|
191 assign(A); changed();
|
samer@0
|
192 }
|
samer@0
|
193
|
samer@0
|
194 /** Symmetrise in place preserving trace.
|
samer@0
|
195 Will fail if matrix is not square. */
|
samer@0
|
196 public void symmetrise()
|
samer@0
|
197 {
|
samer@0
|
198 double a, _G[][]=getArray();
|
samer@0
|
199 for (int i=0; i<n; i++) {
|
samer@0
|
200 for (int j=i+1; j<n; j++) {
|
samer@0
|
201 a=(_G[i][j]+_G[j][i])/2;
|
samer@0
|
202 _G[i][j]=_G[j][i]=a;
|
samer@0
|
203 }
|
samer@0
|
204 }
|
samer@0
|
205 }
|
samer@0
|
206
|
samer@0
|
207 /** Antisymmetrise in place.
|
samer@0
|
208 Will fail if matrix is not square. */
|
samer@0
|
209 public void antisymmetrise()
|
samer@0
|
210 {
|
samer@0
|
211 double a, _G[][]=getArray();
|
samer@0
|
212 for (int i=0; i<n; i++) {
|
samer@0
|
213 for (int j=i+1; j<n; j++) {
|
samer@0
|
214 a=(_G[i][j]-_G[j][i])/2;
|
samer@0
|
215 _G[i][j]=a; _G[j][i]=-a;
|
samer@0
|
216 }
|
samer@0
|
217 _G[i][i]=0;
|
samer@0
|
218 }
|
samer@0
|
219 }
|
samer@0
|
220
|
samer@0
|
221 /** return log(abs(det(this))) (must be square matrix) */
|
samer@0
|
222
|
samer@0
|
223 public double logdet() {
|
samer@0
|
224 int n=getRowDimension();
|
samer@0
|
225 double [][] x=lu().getU().getArray();
|
samer@0
|
226 double L=0;
|
samer@0
|
227 for (int i=0; i<n; i++) L+= Math.log(Math.abs(x[i][i]));
|
samer@0
|
228 return L;
|
samer@0
|
229 }
|
samer@0
|
230 // ................................................
|
samer@0
|
231
|
samer@0
|
232 public Vec getRow(int k) { return new Row(k); }
|
samer@0
|
233 public Vec getColumn(int k) { return new Column(k); }
|
samer@0
|
234
|
samer@0
|
235 public static Vec getDiagonal(final Jama.Matrix A) {
|
samer@0
|
236 return new Vec() {
|
samer@0
|
237 double[][] x=A.getArray();
|
samer@0
|
238
|
samer@0
|
239 public int size() { return x.length; }
|
samer@0
|
240 public double[] array() { return null; }
|
samer@0
|
241 public Mat mat() {
|
samer@0
|
242 return new Mat() {
|
samer@0
|
243 // Mat implementation
|
samer@0
|
244 public int width() { return x.length; }
|
samer@0
|
245 public int height() { return 1; }
|
samer@0
|
246 public double get( int i, int j) { return x[j][j]; }
|
samer@0
|
247 public void set( int i, int j, double t) { x[j][j]=t; }
|
samer@0
|
248 };
|
samer@0
|
249 }
|
samer@0
|
250 public Iterator iterator() {
|
samer@0
|
251 return new Iterator() {
|
samer@0
|
252 int i=0, n=x.length;
|
samer@0
|
253 public void rewind() { i=0; }
|
samer@0
|
254 public boolean more() { return i<n; }
|
samer@0
|
255 public double next() {
|
samer@0
|
256 double y=x[i][i]; i++; return y;
|
samer@0
|
257 }
|
samer@0
|
258 };
|
samer@0
|
259 }
|
samer@0
|
260 };
|
samer@0
|
261 }
|
samer@0
|
262
|
samer@0
|
263 private abstract class Slice implements Vec, Vec.Iterator
|
samer@0
|
264 {
|
samer@0
|
265 protected int i, j, n;
|
samer@0
|
266
|
samer@0
|
267 Slice(int n, int j) { this.n=n; this.j=j; i=0; }
|
samer@0
|
268
|
samer@0
|
269 // Vec implementation
|
samer@0
|
270 public final Vec.Iterator iterator() { i=0; return this; }
|
samer@0
|
271 public final int size() { return n; }
|
samer@0
|
272 public final void rewind() { i=0; }
|
samer@0
|
273 public final boolean more() { return i<n; }
|
samer@0
|
274 }
|
samer@0
|
275
|
samer@0
|
276 private class Row extends Slice {
|
samer@0
|
277 double [] x;
|
samer@0
|
278
|
samer@0
|
279 public Row(int rownum) {
|
samer@0
|
280 super(Matrix.this.getColumnDimension(),rownum);
|
samer@0
|
281 x=getArray()[rownum];
|
samer@0
|
282 }
|
samer@0
|
283
|
samer@0
|
284 public final double next() { return x[i++]; }
|
samer@0
|
285 public final double[] array() { return x; }
|
samer@0
|
286 public final Mat mat() {
|
samer@0
|
287 return new Mat() {
|
samer@0
|
288 // Mat implementation
|
samer@0
|
289 public int width() { return Row.this.n; }
|
samer@0
|
290 public int height() { return 1; }
|
samer@0
|
291 public double get( int i, int j) { return x[j]; }
|
samer@0
|
292 public void set( int i, int j, double t) { x[j]=t; }
|
samer@0
|
293 };
|
samer@0
|
294 }
|
samer@0
|
295 }
|
samer@0
|
296
|
samer@0
|
297 private class Column extends Slice {
|
samer@0
|
298 double [][] x;
|
samer@0
|
299 int j;
|
samer@0
|
300
|
samer@0
|
301 public Column(int colnum) {
|
samer@0
|
302 super(Matrix.this.getRowDimension(),colnum);
|
samer@0
|
303 x=getArray();
|
samer@0
|
304 j=colnum;
|
samer@0
|
305 }
|
samer@0
|
306
|
samer@0
|
307 public final double next() { return x[i++][j]; }
|
samer@0
|
308 public final double[] array() { return null; }
|
samer@0
|
309 public final Mat mat() {
|
samer@0
|
310 return new Mat() {
|
samer@0
|
311 public final int width() { return Column.this.n; }
|
samer@0
|
312 public final int height() { return 1; }
|
samer@0
|
313 public final double get( int i, int k) { return x[k][j]; }
|
samer@0
|
314 public final void set( int i, int k, double t) { x[k][j]=t; }
|
samer@0
|
315 };
|
samer@0
|
316 }
|
samer@0
|
317 }
|
samer@0
|
318 }
|