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