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="https://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 }