001         package com.croftsoft.apps.insight;
002    
003         import java.awt.Point;
004    
005         public class Matrix {
006         //////////////////////////////////////////////////////////////////////
007         // Matrix.java v0.0 (C) Copyright 1996 David Wallace Croft.
008         // 1996-08-24
009         //////////////////////////////////////////////////////////////////////
010    
011         int             rows;
012         int             columns;
013         double [ ] [ ]  data;
014    
015         public Matrix ( int  rows, int  columns ) {
016         //////////////////////////////////////////////////////////////////////
017         // Constructor method
018         //////////////////////////////////////////////////////////////////////
019           this.rows    = rows;
020           this.columns = columns;
021           this.data    = new double [ rows ] [ columns ];
022         }
023    
024         public Matrix ( Matrix  old ) {
025         //////////////////////////////////////////////////////////////////////
026         // Constructor method
027         //////////////////////////////////////////////////////////////////////
028           this ( old.rows, old.columns );
029           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
030             for ( int index_col = 0; index_col < this.columns; index_col++ ) {
031               this.data [ index_row ] [ index_col ]
032                 = old.data [ index_row ] [ index_col ];
033             }
034           }
035         }
036    
037         //////////////////////////////////////////////////////////////////////
038         //////////////////////////////////////////////////////////////////////
039    
040         public Matrix  add ( double  addend ) {
041         //////////////////////////////////////////////////////////////////////
042           Matrix  new_Matrix = new Matrix ( this );
043         //////////////////////////////////////////////////////////////////////
044           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
045           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
046             new_Matrix.data [ index_row ] [ index_col ] += addend;
047           }
048           }
049           return new_Matrix;
050         }
051    
052         public Matrix  add ( Matrix  addend ) {
053         //////////////////////////////////////////////////////////////////////
054           if ( ( this.rows    != addend.rows    )
055             || ( this.columns != addend.columns ) ) {
056             throw new ArrayIndexOutOfBoundsException (
057               "Matrix.add ( Matrix ):  columns and rows not equal" );
058           }
059           Matrix  new_Matrix = new Matrix ( this );
060         //////////////////////////////////////////////////////////////////////
061           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
062           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
063             new_Matrix.data [ index_row ] [ index_col ]
064               += addend.data [ index_row ] [ index_col ];
065           }
066           }
067           return new_Matrix;
068         }
069    
070         public double [ ]  array_column ( int  column ) {
071         //////////////////////////////////////////////////////////////////////
072           double [ ]  arr_col = new double [ this.rows ];
073         //////////////////////////////////////////////////////////////////////
074           for ( int index_row = 0; index_row < this.rows; index_row++ ) {
075             arr_col [ index_row ] = this.data [ index_row ] [ column ];
076           }
077           return arr_col;
078         }
079    
080         public Matrix  clip ( double  min, double  max ) {
081         //////////////////////////////////////////////////////////////////////
082           Matrix  new_Matrix = new Matrix ( this );
083         //////////////////////////////////////////////////////////////////////
084           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
085           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
086             if ( this.data [ index_row ] [ index_col ] < min )
087               new_Matrix.data [ index_row ] [ index_col ] = min;
088             else if ( this.data [ index_row ] [ index_col ] > max )
089               new_Matrix.data [ index_row ] [ index_col ] = max;
090           }
091           }
092           return new_Matrix;
093         }
094    
095         static public void  demo ( ) {
096         //////////////////////////////////////////////////////////////////////
097           Matrix  left  = new Matrix ( 2, 3 );
098           Matrix  right = new Matrix ( 3, 4 );
099           for ( int index_row = 0; index_row < left.rows; index_row++ ) {
100             for ( int index_col = 0; index_col < left.columns; index_col++ ) {
101               left.data [ index_row ] [ index_col ] = index_row + index_col;
102             }
103           }
104           for ( int index_row = 0; index_row < right.rows; index_row++ ) {
105             for ( int index_col = 0; index_col < right.columns; index_col++ ) {
106               right.data [ index_row ] [ index_col ] = index_row + index_col;
107             }
108           }
109           left.display ( );
110           System.out.println ( "" );
111           right.display ( );
112           System.out.println ( "" );
113           Matrix  product = multiply ( left, right );
114           product.display ( );
115           System.out.println ( "" );
116           Matrix  transposed = product.transpose ( );
117           transposed.display ( );
118           System.out.println ( "" );
119           Matrix  sigmoided = transposed.sigmoid ( );
120           sigmoided.display ( );
121         }
122    
123         public void  display ( ) {
124         //////////////////////////////////////////////////////////////////////
125           String  line_String;
126         //////////////////////////////////////////////////////////////////////
127           for ( int index_row = 0; index_row < this.rows; index_row++ ) {
128             line_String = "";
129             for ( int index_col = 0; index_col < this.columns; index_col++ ) {
130               line_String += this.data [ index_row ] [ index_col ] + " ";
131             }
132             System.out.println ( line_String );
133           }
134         }
135    
136         public Matrix  divide ( double  factor ) {
137         //////////////////////////////////////////////////////////////////////
138           Matrix  new_Matrix = new Matrix ( this );
139         //////////////////////////////////////////////////////////////////////
140           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
141           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
142             new_Matrix.data [ index_row ] [ index_col ] /= factor;
143           }
144           }
145           return new_Matrix;
146         }
147    
148         static public Matrix  identity ( Matrix  old ) {
149         //////////////////////////////////////////////////////////////////////
150           Matrix  new_Matrix = new Matrix ( old.rows, old.columns );
151         //////////////////////////////////////////////////////////////////////
152           for ( int index_row = 0; index_row < old.rows   ; index_row++ ) {
153           for ( int index_col = 0; index_col < old.columns; index_col++ ) {
154             new_Matrix.data [ index_row ] [ index_col ] = 1.0;
155           }
156           }
157           return new_Matrix;
158         }
159    
160         public Point  max_indices ( ) {
161         //////////////////////////////////////////////////////////////////////
162           int  max_row = 0;
163           int  max_col = 0;
164         //////////////////////////////////////////////////////////////////////
165           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
166           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
167             if ( this.data [ index_row ] [ index_col ]
168               > this.data [ max_row ] [ max_col ] ) {
169               max_row = index_row;
170               max_col = index_col;
171             }
172           }
173           }
174           return new Point ( max_row, max_col );
175         }
176    
177         public Matrix  multiply ( double  factor ) {
178         //////////////////////////////////////////////////////////////////////
179           Matrix  new_Matrix = new Matrix ( this );
180         //////////////////////////////////////////////////////////////////////
181           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
182           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
183             new_Matrix.data [ index_row ] [ index_col ] *= factor;
184           }
185           }
186           return new_Matrix;
187         }
188    
189         public Matrix  multiply ( Matrix  right ) {
190         //////////////////////////////////////////////////////////////////////
191           return multiply ( this, right );
192         }
193    
194         static public Matrix  multiply ( Matrix  left, Matrix  right ) {
195         //////////////////////////////////////////////////////////////////////
196           if ( left.columns != right.rows ) {
197             throw new ArrayIndexOutOfBoundsException (
198               "Matrix.multiply:  left.columns != right.rows" );
199           }
200           Matrix  product = new Matrix ( left.rows, right.columns );
201         //////////////////////////////////////////////////////////////////////
202           for ( int index_row = 0; index_row < product.rows; index_row++ ) {
203             for ( int index_col = 0; index_col < product.columns; index_col++ ) {
204               product.data [ index_row ] [ index_col ] = 0.0;
205               for ( int index = 0; index < left.columns; index++ ) {
206                 product.data [ index_row ] [ index_col ]
207                   += left.data [ index_row ] [ index ]
208                   * right.data [ index ] [ index_col ];
209               }
210             }
211           }
212           return product;
213         }
214    
215         static public Matrix  multiply_elements ( Matrix  a, Matrix  b ) {
216         //////////////////////////////////////////////////////////////////////
217           if ( ( a.rows != b.rows ) || ( a.columns != b.columns ) ) {
218             throw new ArrayIndexOutOfBoundsException (
219               "Matrix.multiply_pairwise:  rows or columns not equal" );
220           }
221           Matrix  product = new Matrix ( a.rows, a.columns );
222         //////////////////////////////////////////////////////////////////////
223           for ( int index_row = 0; index_row < a.rows   ; index_row++ ) {
224           for ( int index_col = 0; index_col < a.columns; index_col++ ) {
225             product.data [ index_row ] [ index_col ]
226               = a.data [ index_row ] [ index_col ]
227               * b.data [ index_row ] [ index_col ];
228           }
229           }
230           return product;
231         }
232    
233         public Matrix  randomize_uniform ( double  min, double  max ) {
234         //////////////////////////////////////////////////////////////////////
235           Matrix  new_Matrix = new Matrix ( this.rows, this.columns );
236         //////////////////////////////////////////////////////////////////////
237           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
238           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
239             new_Matrix.data [ index_row ] [ index_col ]
240               = Croft_Random.uniform ( min, max );
241           }
242           }
243           return new_Matrix;
244         }
245    
246         public Matrix  sigmoid ( ) {
247         //////////////////////////////////////////////////////////////////////
248           Matrix  new_Matrix = new Matrix ( this.rows, this.columns );
249         //////////////////////////////////////////////////////////////////////
250           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
251           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
252             new_Matrix.data [ index_row ] [ index_col ]
253               = Croft_Math.sigmoid ( this.data [ index_row ] [ index_col ] );
254           }
255           }
256           return new_Matrix;
257         }
258    
259         public Matrix  sigmoid_derivative ( ) {
260         //////////////////////////////////////////////////////////////////////
261           Matrix  new_Matrix = new Matrix ( this.rows, this.columns );
262         //////////////////////////////////////////////////////////////////////
263           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
264           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
265             new_Matrix.data [ index_row ] [ index_col ]
266               = Croft_Math.sigmoid_derivative
267               ( this.data [ index_row ] [ index_col ] );
268           }
269           }
270           return new_Matrix;
271         }
272    
273         public Matrix  square_elements ( ) {
274         //////////////////////////////////////////////////////////////////////
275           Matrix  new_Matrix = new Matrix ( this.rows, this.columns );
276           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
277           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
278             new_Matrix.data [ index_row ] [ index_col ]
279               = this.data [ index_row ] [ index_col ]
280               * this.data [ index_row ] [ index_col ];
281           }
282           }
283           return new_Matrix;
284         }
285    
286         public Matrix  sub_matrix (
287           int  row_start, int  row_end,
288           int  col_start, int  col_end ) {
289         //////////////////////////////////////////////////////////////////////
290         //  Note that the first row is row 0.
291         //////////////////////////////////////////////////////////////////////
292           Matrix  sub
293             = new Matrix ( row_end - row_start + 1, col_end - col_start + 1 );
294         //////////////////////////////////////////////////////////////////////
295           for ( int index_row = 0; index_row < sub.rows   ; index_row++ ) {
296           for ( int index_col = 0; index_col < sub.columns; index_col++ ) {
297             sub.data [ index_row ] [ index_col ]
298               = this.data [ index_row + row_start ] [ index_col + col_start ];
299           }
300           }
301           return sub;
302         }
303    
304         public Matrix  subtract ( Matrix  subtractor ) {
305         //////////////////////////////////////////////////////////////////////
306           if ( ( this.rows    != subtractor.rows    )
307             || ( this.columns != subtractor.columns ) ) {
308             throw new ArrayIndexOutOfBoundsException (
309               "Matrix.subtract ( Matrix ):  columns and rows not equal" );
310           }
311           Matrix  new_Matrix = new Matrix ( this );
312         //////////////////////////////////////////////////////////////////////
313           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
314           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
315             new_Matrix.data [ index_row ] [ index_col ]
316               -= subtractor.data [ index_row ] [ index_col ];
317           }
318           }
319           return new_Matrix;
320         }
321    
322         public double  sum ( ) {
323         //////////////////////////////////////////////////////////////////////
324           double  temp = 0.0;
325         //////////////////////////////////////////////////////////////////////
326           for ( int index_row = 0; index_row < this.rows   ; index_row++ ) {
327           for ( int index_col = 0; index_col < this.columns; index_col++ ) {
328             temp += this.data [ index_row ] [ index_col ];
329           }
330           }
331           return temp;
332         }
333    
334         public Matrix  transpose ( ) {
335         //////////////////////////////////////////////////////////////////////
336           Matrix  transposed = new Matrix ( this.columns, this.rows );
337         //////////////////////////////////////////////////////////////////////
338           for ( int index_row = 0;
339                     index_row < transposed.rows;
340                     index_row++ ) {
341             for ( int index_col = 0;
342                       index_col < transposed.columns;
343                       index_col++ ) {
344               transposed.data [ index_row ] [ index_col ]
345                 = this.data [ index_col ] [ index_row ];
346             }
347           }
348           return transposed;
349         }
350    
351         //////////////////////////////////////////////////////////////////////
352         //////////////////////////////////////////////////////////////////////
353         }