-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGeneralMatrix.java
More file actions
308 lines (290 loc) · 9.46 KB
/
GeneralMatrix.java
File metadata and controls
308 lines (290 loc) · 9.46 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
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/*
* PROJECT III: GeneralMatrix.java
*
* This file contains a template for the class GeneralMatrix. Not all methods
* are implemented. Make sure you have carefully read the project formulation
* before starting to work on this file. You will also need to have completed
* the Matrix class.
*
* Remember not to change the names, parameters or return types of any
* variables in this file!
*
* The function of the methods and instance variables are outlined in the
* comments directly above them.
*/
import java.util.Arrays;
import java.util.Random;
public class GeneralMatrix extends Matrix {
/**
* This instance variable stores the elements of the matrix.
*/
private double[][] data;
/**
* Constructor function: should initialise m and n through the Matrix
* constructor and set up the data array.
*
* @param m The first dimension of the array.
* @param n The second dimension of the array.
*/
public GeneralMatrix(int m, int n) throws MatrixException {
super(m,n);
if (m < 1 || n < 1) {
throw new MatrixException("Matrix dimension must be greater than 0.");
}else {
data = new double[m][n];
}
}
/**
* Constructor function. This is a copy constructor; it should create a
* copy of the matrix A.
*
* @param A The matrix to create a copy of.
*/
public GeneralMatrix(GeneralMatrix A) {
super(A.m,A.n);
data = new double[A.m][A.n];
int i = 0, j = 0;
while(i < A.m) {
while (j < A.n) {
data[i][j] = A.getIJ(i,j);
j++;
}
j = 0;
i++;
}
}
/**
* Getter function: return the (i,j)'th entry of the matrix.
*
* @param i The location in the first co-ordinate.
* @param j The location in the second co-ordinate.
* @return The (i,j)'th entry of the matrix.
*/
public double getIJ(int i, int j) {
if (i < 0 || j < 0){
throw new MatrixException("Matrix indices must be 0 or greater");
} else if (i >= m || j >= n) {
throw new MatrixException("Matrix indices must be less than no. of rows/columns");
} else {
return this.data[i][j];
}
}
/**
* Setter function: set the (i,j)'th entry of the data array.
*
* @param i The location in the first co-ordinate.
* @param j The location in the second co-ordinate.
* @param val The value to set the (i,j)'th entry to.
*/
public void setIJ(int i, int j, double val) {
if (i < 0 || j < 0){
throw new MatrixException("Matrix indices must be 0 or greater");
} else if (i >= m || j >= n) {
throw new MatrixException("Matrix indices must be less than no. of rows/columns");
} else {
this.data[i][j] = val;
}
}
/**
* Return the determinant of this matrix.
*
* @return The determinant of the matrix.
*/
public double determinant() {
double[] d = new double[1];
GeneralMatrix LU = this.decomp(d);
double det = LU.getIJ(0,0);
for(int i = 1; i < this.m; i++) {
det = det*LU.getIJ(i,i);
}
det = det * d[0];
return det;
}
/**
* Add the matrix to another matrix A.
*
* @param A The Matrix to add to this matrix.
* @return The sum of this matrix with the matrix A.
*/
public Matrix add(Matrix A) {
if ((A.m == this.m) && (A.n == this.n)) {
GeneralMatrix B = new GeneralMatrix(A.m,A.n);
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
double sum = this.getIJ(i,j) + A.getIJ(i,j);
B.setIJ(i,j,sum);
}
}
return B;
}else {
throw new MatrixException("Dimensions of matrices must be equal for addition.");
}
}
/**
* Multiply the matrix by another matrix A. This is a _left_ product,
* i.e. if this matrix is called B then it calculates the product BA.
*
* @param A The Matrix to multiply by.
* @return The product of this matrix with the matrix A.
*/
public Matrix multiply(Matrix A) {
if (this.n == A.m) {
GeneralMatrix C = new GeneralMatrix(this.m,A.n);
for (int i = 0; i < A.m; i++) {
for (int j = 0; j < A.n; j++) {
double sum = 0;
for (int k = 0; k < this.n; k++) {
double prod = this.getIJ(i,k) * A.getIJ(k,j);
sum = sum + prod;
}
C.setIJ(i,j,sum);
}
}
return C;
}else {
throw new MatrixException("No. of columns of left matrix must equal no. of rows of right matrix.");
}
}
/**
* Multiply the matrix by a scalar.
*
* @param a The scalar to multiply the matrix by.
* @return The product of this matrix with the scalar a.
*/
public Matrix multiply(double a) {
GeneralMatrix C = new GeneralMatrix(this.m,this.n);
for (int i = 0; i < this.m; i++) {
for (int j = 0; j < this.n; j++) {
double prod = this.getIJ(i,j) * a;
C.setIJ(i,j,prod);
}
}
return C;
}
/**
* Populates the matrix with random numbers which are uniformly
* distributed between 0 and 1.
*/
public void random() {
for (int i = 0; i < this.m; i++) {
for (int j = 0; j < this.n; j++) {
Random r = new Random();
double R = r.nextDouble();
this.setIJ(i,j,R);
}
}
}
/**
* Returns the LU decomposition of this matrix; i.e. two matrices L and U
* so that A = LU, where L is lower-diagonal and U is upper-diagonal.
*
* On exit, decomp returns the two matrices in a single matrix by packing
* both matrices as follows:
*
* [ u_11 u_12 u_13 u_14 ]
* [ l_21 u_22 u_23 u_24 ]
* [ l_31 l_32 u_33 u_34 ]
* [ l_41 l_42 l_43 l_44 ]
*
* where u_ij are the elements of U and l_ij are the elements of l. When
* calculating the determinant you will need to multiply by the value of
* d[0] calculated by the function.
*
* If the matrix is singular, then the routine throws a MatrixException.
*
* This method is an adaptation of the one found in the book "Numerical
* Recipies in C" (see online for more details).
*
* @param d An array of length 1. On exit, the value contained in here
* will either be 1 or -1, which you can use to calculate the
* correct sign on the determinant.
* @return The LU decomposition of the matrix.
*/
public GeneralMatrix decomp(double[] d) {
// This method is complete. You should not even attempt to change it!!
if (n != m)
throw new MatrixException("Matrix is not square");
if (d.length != 1)
throw new MatrixException("d should be of length 1");
int i, imax = -10, j, k;
double big, dum, sum, temp;
double[] vv = new double[n];
GeneralMatrix a = new GeneralMatrix(this);
d[0] = 1.0;
for (i = 1; i <= n; i++) {
big = 0.0;
for (j = 1; j <= n; j++)
if ((temp = Math.abs(a.data[i-1][j-1])) > big)
big = temp;
if (big == 0.0)
throw new MatrixException("Matrix is singular");
vv[i-1] = 1.0/big;
}
for (j = 1; j <= n; j++) {
for (i = 1; i < j; i++) {
sum = a.data[i-1][j-1];
for (k = 1; k < i; k++)
sum -= a.data[i-1][k-1]*a.data[k-1][j-1];
a.data[i-1][j-1] = sum;
}
big = 0.0;
for (i = j; i <= n; i++) {
sum = a.data[i-1][j-1];
for (k = 1; k < j; k++)
sum -= a.data[i-1][k-1]*a.data[k-1][j-1];
a.data[i-1][j-1] = sum;
if ((dum = vv[i-1]*Math.abs(sum)) >= big) {
big = dum;
imax = i;
}
}
if (j != imax) {
for (k = 1; k <= n; k++) {
dum = a.data[imax-1][k-1];
a.data[imax-1][k-1] = a.data[j-1][k-1];
a.data[j-1][k-1] = dum;
}
d[0] = -d[0];
vv[imax-1] = vv[j-1];
}
if (a.data[j-1][j-1] == 0.0)
a.data[j-1][j-1] = 1.0e-20;
if (j != n) {
dum = 1.0/a.data[j-1][j-1];
for (i = j+1; i <= n; i++)
a.data[i-1][j-1] *= dum;
}
}
return a;
}
/*
* Your tester function should go here.
*/
public static void main(String[] args) {
System.out.println("Expected: same 2*2 matrix twice, different 2*2 matrix, 2*3 matrix");
GeneralMatrix B = new GeneralMatrix(2,2);
GeneralMatrix D = new GeneralMatrix(2,3);
GeneralMatrix E = new GeneralMatrix(2,2);
B.random();
D.random();
E.random();
GeneralMatrix C = new GeneralMatrix(B);
System.out.println(B.toString());
System.out.println(C.toString());
System.out.println(E.toString());
System.out.println(D.toString());
System.out.println("Expected: top left entry of first matrix");
System.out.println(B.getIJ(0,0));
System.out.println("Expected: 2*2 matrix with 2 in bottom right corner");
B.setIJ(1,1,2);
System.out.println(B.toString());
System.out.println("Expected: det of first matrix");
System.out.println(B.determinant());
System.out.println("Expected: sum of 2*2 matrices, 2*3 matrix, 2*2 matrix");
System.out.println(B.add(E).toString());
System.out.println(B.multiply(D).toString());
System.out.println(B.multiply(E).toString());
System.out.println("Expected: 2* first 2*2 matrix");
System.out.println(B.multiply(2).toString());
}
}