View Javadoc

1   // Matrix.java
2   // a simple java file for a standard class
3   
4   package math.utils;
5   
6   // Imports
7   
8   /**
9    * class Matrix
10   */
11  public class Matrix {
12  
13      // ===================================================================
14      // constants
15  
16      // ===================================================================
17      // class variables
18  
19      /** the number of rows. */
20      private int        nRows;
21      /** the number of columns. */
22      private int        nCols;
23  
24      /** the element array of the matrix. */
25      private double[][] el;
26  
27      // ===================================================================
28      // constructors
29  
30      /** Main constructor */
31  
32      /**
33       * Construct a new Matrix, with 1 row and 1 column, initialized to 1.
34       */
35      public Matrix() {
36          this(1, 1);
37      }
38  
39      /** init a new Matrix with nbRows rows, and nbCols columns. */
40      public Matrix(int nbRows, int nbCols) {
41          nRows = nbRows;
42          nCols = nbCols;
43          el = new double[nRows][nCols];
44          setToIdentity();
45      }
46  
47      /**
48       * Construct a new Matrix, initialized with the given coefficients.
49       */
50      public Matrix(double[][] coef) {
51          if (coef==null) {
52              nRows = 1;
53              nCols = 1;
54              el = new double[nRows][nCols];
55              setToIdentity();
56              return;
57          }
58  
59          nRows = coef.length;
60          nCols = coef[0].length;
61          el = new double[nRows][nCols];
62          for (int r = 0; r<nRows; r++)
63              for (int c = 0; c<nCols; c++)
64                  el[r][c] = coef[r][c];
65      }
66  
67      // ===================================================================
68      // accessors
69  
70      /**
71       * return the coef. row and col are between 1 and the number of rows and
72       * columns.
73       */
74      public double getCoef(int row, int col) {
75          return el[row-1][col-1];
76      }
77  
78      /** return the number of rows. */
79      public int getRows() {
80          return nRows;
81      }
82  
83      /** return the number of columns. */
84      public int getColumns() {
85          return nCols;
86      }
87  
88      /**
89       * return true if the matrix is square, i.e. the number of rows equals the
90       * number of columns.
91       */
92      public boolean isSquare() {
93          return (nCols==nRows);
94      }
95  
96      // ===================================================================
97      // modifiers
98  
99      /**
100      * set the coef to the given value. row and col are between 1 and the number
101      * of rows and columns.
102      */
103     public void setCoef(int row, int col, double coef) {
104         el[row-1][col-1] = coef;
105     }
106 
107     // ===================================================================
108     // computation methods
109 
110     /**
111      * return the result of the multiplication of the matriux with another one.
112      * The content of the matrix is not modified.
113      */
114     public Matrix multiplyWith(Matrix matrix) {
115 
116         // check sizes of the matrices
117         if (nCols!=matrix.nRows) {
118             System.out.println("Matrices size don't match !");
119             return null;
120         }
121         double sum;
122 
123         Matrix m = new Matrix(nRows, matrix.nCols);
124 
125         for (int r = 0; r<m.nRows; r++)
126             for (int c = 0; c<m.nCols; c++) {
127                 sum = 0;
128                 for (int i = 0; i<nCols; i++)
129                     sum += el[r][i]*matrix.el[i][c];
130                 m.el[r][c] = sum;
131             }
132 
133         return m;
134     }
135 
136     /**
137      * return the result of the multiplication of the matrix with the given
138      * vector. The content of the matrix is not modified.
139      */
140     public double[] multiplyWith(double[] coefs) {
141 
142         if (coefs==null) {
143             System.out.println("no data to compute");
144             return null;
145         }
146 
147         // check sizes of matrix and vector
148         if (coefs.length!=nCols) {
149             System.out.println("Matrices size don't match !");
150             return null;
151         }
152         double sum;
153         double[] res = new double[nRows];
154 
155         for (int r = 0; r<nRows; r++) {
156             sum = 0;
157             for (int c = 0; c<nCols; c++)
158                 sum += el[r][c]*coefs[c];
159             res[r] = sum;
160         }
161         return res;
162     }
163 
164     /**
165      * return the result of the multiplication of the matrix with the given
166      * vector. The content of the matrix is not modified.
167      */
168     public double[] multiplyWith(double[] src, double[] res) {
169 
170         if (src==null) {
171             System.out.println("no data to compute");
172             return null;
173         }
174 
175         // check sizes of matrix and vector
176         if (src.length!=nCols) {
177             System.out.println("Matrices size don't match !");
178             return null;
179         }
180         if (src.length!=res.length)
181             res = new double[nRows];
182 
183         double sum;
184 
185         for (int r = 0; r<nRows; r++) {
186             sum = 0;
187             for (int c = 0; c<nCols; c++)
188                 sum += el[r][c]*src[c];
189             res[r] = sum;
190         }
191         return res;
192     }
193 
194     /** transpose the matrix, changing the inner coefficients. */
195     public void transpose() {
196         int tmp = nCols;
197         nCols = nRows;
198         nRows = tmp;
199         double[][] oldData = el;
200         el = new double[nRows][nCols];
201 
202         for (int r = 0; r<nRows; r++)
203             for (int c = 0; c<nCols; c++)
204                 el[r][c] = oldData[c][r];
205     }
206 
207     /**
208      * get the transposed matrix, without changing the inner coefficients of the
209      * original matrix.
210      */
211     public Matrix getTranspose() {
212         Matrix mat = new Matrix(nCols, nRows);
213 
214         for (int r = 0; r<nRows; r++)
215             for (int c = 0; c<nCols; c++)
216                 mat.el[c][r] = el[r][c];
217         return mat;
218     }
219 
220     /**
221      * compute the solution of a linear system, using the Gauss-Jordan
222      * algorithm. The inner coefficients of the matrix are not modified.
223      */
224     public double[] solve(double vector[]) {
225 
226         if (vector==null)
227             throw new NullPointerException();
228         if (vector.length!=nRows) {
229             System.out.println("matrix and vector dimensions do not match!");
230             return null;
231         }
232         if (nCols!=nRows) {
233             System.out.println("Try to invert non square Matrix.");
234             return null;
235         }
236 
237         double[] res = new double[vector.length];
238         for (int i = 0; i<nRows; i++)
239             res[i] = vector[i];
240 
241         Matrix mat = new Matrix(el);
242 
243         int r, c; // row and column indices
244         int p, r2; // pivot index, and secondary row index
245         double pivot, tmp;
246 
247         // for each line of the matrix
248         for (r = 0; r<nRows; r++) {
249 
250             p = r;
251             // look for the first non-null pivot
252             while ((Math.abs(mat.el[p][r])<1e-15)&&(p<=nRows))
253                 p++;
254 
255             if (p==nRows) {
256                 System.out.println("Degenerated linear system :");
257                 return null;
258             }
259 
260             // swap the current line and the pivot
261             for (c = 0; c<nRows; c++) {
262                 tmp = mat.el[r][c];
263                 mat.el[r][c] = mat.el[p][c];
264                 mat.el[p][c] = tmp;
265             }
266 
267             // swap the corresponding values in the vector
268             tmp = res[r];
269             res[r] = res[p];
270             res[p] = tmp;
271 
272             pivot = mat.el[r][r];
273 
274             // divide elements of the current line by the pivot
275             for (c = r+1; c<nRows; c++)
276                 mat.el[r][c] /= pivot;
277             res[r] /= pivot;
278             mat.el[r][r] = 1;
279 
280             // update other lines, before current line...
281             for (r2 = 0; r2<r; r2++) {
282                 pivot = mat.el[r2][r];
283                 for (c = r+1; c<nRows; c++)
284                     mat.el[r2][c] -= pivot*mat.el[r][c];
285                 res[r2] -= pivot*res[r];
286                 mat.el[r2][r] = 0;
287             }
288 
289             // and after current line
290             for (r2 = r+1; r2<nRows; r2++) {
291                 pivot = mat.el[r2][r];
292                 for (c = r+1; c<nRows; c++)
293                     mat.el[r2][c] -= pivot*mat.el[r][c];
294                 res[r2] -= pivot*res[r];
295                 mat.el[r2][r] = 0;
296             }
297         }
298 
299         return res;
300     }
301 
302     // ===================================================================
303     // general methods
304 
305     /**
306      * Fill the matrix with zeros everywhere, except on the main diagonal,
307      * filled with ones.
308      */
309     public void setToIdentity() {
310         for (int r = 0; r<nRows; r++)
311             for (int c = 0; c<nCols; c++)
312                 el[r][c] = 0;
313         for (int i = Math.min(nRows, nCols)-1; i>=0; i--)
314             el[i][i] = 1;
315     }
316 
317     /**
318      * return a String representation of the elements of the Matrix
319      */
320     @Override
321     public String toString() {
322         String res = new String("");
323         res = res.concat("Matrix size : "+Integer.toString(nRows)+" rows and "
324                 +Integer.toString(nCols)+" columns.\n");
325         for (int r = 0; r<nRows; r++) {
326             for (int c = 0; c<nCols; c++)
327                 res = res.concat(Double.toString(el[r][c])).concat(" ");
328             res = res.concat(new String("\n"));
329         }
330         return res;
331     }
332 }