1 package JSci.maths.matrices; 2 3 import JSci.GlobalSettings; 4 import JSci.maths.Mapping; 5 import JSci.maths.DimensionException; 6 import JSci.maths.vectors.AbstractDoubleVector; 7 import JSci.maths.vectors.DoubleVector; 8 9 15 public final class DoubleSparseSquareMatrix extends AbstractDoubleSquareMatrix { 16 19 private double elements[]; 20 26 private int colPos[]; 27 33 private int rows[]; 34 38 public DoubleSparseSquareMatrix(final int size) { 39 super(size); 40 elements=new double[0]; 41 colPos=new int[0]; 42 rows=new int[numRows+1]; 43 } 44 49 public DoubleSparseSquareMatrix(final double array[][]) { 50 super(array.length); 51 rows=new int[numRows+1]; 52 int n=0; 53 for(int i=0;i<numRows;i++) { 54 if(array[i].length != array.length) 55 throw new MatrixDimensionException("Array is not square."); 56 for(int j=0;j<numCols;j++) { 57 if(Math.abs(array[i][j])>GlobalSettings.ZERO_TOL) 58 n++; 59 } 60 } 61 elements=new double[n]; 62 colPos=new int[n]; 63 n=0; 64 for(int i=0;i<numRows;i++) { 65 rows[i]=n; 66 for(int j=0;j<numCols;j++) { 67 if(Math.abs(array[i][j])>GlobalSettings.ZERO_TOL) { 68 elements[n]=array[i][j]; 69 colPos[n]=j; 70 n++; 71 } 72 } 73 } 74 rows[numRows]=n; 75 } 76 80 public boolean equals(AbstractDoubleSquareMatrix m, double tol) { 81 if(numRows==m.numRows && numCols==m.numCols) { 82 if(m instanceof DoubleSparseSquareMatrix) { 83 return this.equals((DoubleSparseSquareMatrix)m); 84 } else { 85 double sumSqr = 0; 86 for(int i=0;i<numRows;i++) { 87 for(int j=0;j<numCols;j++) { 88 double delta = getElement(i,j)-m.getElement(i,j); 89 sumSqr += delta*delta; 90 } 91 } 92 return (sumSqr <= tol*tol); 93 } 94 } else 95 return false; 96 } 97 public final boolean equals(DoubleSparseSquareMatrix m) { 98 return equals(m, GlobalSettings.ZERO_TOL); 99 } 100 public boolean equals(DoubleSparseSquareMatrix m, double tol) { 101 if(numRows==m.numRows && numCols==m.numCols) { 102 if(colPos.length!=m.colPos.length) 103 return false; 104 for(int i=1;i<rows.length;i++) { 105 if(rows[i]!=m.rows[i]) 106 return false; 107 } 108 double sumSqr = 0.0; 109 for(int i=1;i<colPos.length;i++) { 110 if(colPos[i]!=m.colPos[i]) 111 return false; 112 double delta = elements[i] - m.elements[i]; 113 sumSqr += delta*delta; 114 } 115 return (sumSqr <= tol*tol); 116 } else 117 return false; 118 } 119 122 public String toString() { 123 final StringBuffer buf=new StringBuffer (numRows*numCols); 124 for(int i=0;i<numRows;i++) { 125 for(int j=0;j<numCols;j++) { 126 buf.append(getElement(i,j)); 127 buf.append(' '); 128 } 129 buf.append('\n'); 130 } 131 return buf.toString(); 132 } 133 137 public AbstractIntegerMatrix toIntegerMatrix() { 138 final int ans[][]=new int[numRows][numCols]; 139 for(int i=0;i<numRows;i++) { 140 for(int j=0;j<numCols;j++) 141 ans[i][j]=Math.round((float)getElement(i,j)); 142 } 143 return new IntegerSquareMatrix(ans); 144 } 145 149 public AbstractComplexMatrix toComplexMatrix() { 150 final double arrayRe[][]=new double[numRows][numCols]; 151 for(int i=0;i<numRows;i++) { 152 for(int j=0;j<numCols;j++) 153 arrayRe[i][j]=getElement(i,j); 154 } 155 return new ComplexSquareMatrix(arrayRe,new double[numRows][numCols]); 156 } 157 163 public double getElement(final int i, final int j) { 164 if(i>=0 && i<numRows && j>=0 && j<numCols) { 165 for(int k=rows[i];k<rows[i+1];k++) { 166 if(colPos[k]==j) 167 return elements[k]; 168 } 169 return 0.0; 170 } else 171 throw new MatrixDimensionException(getInvalidElementMsg(i,j)); 172 } 173 180 public void setElement(final int i, final int j, final double x) { 181 if(i>=0 && i<numRows && j>=0 && j<numCols) { 182 if(Math.abs(x)<=GlobalSettings.ZERO_TOL) 183 return; 184 for(int k=rows[i];k<rows[i+1];k++) { 185 if(colPos[k]==j) { 186 elements[k]=x; 187 return; 188 } 189 } 190 final double oldMatrix[]=elements; 191 final int oldColPos[]=colPos; 192 elements=new double[oldMatrix.length+1]; 193 colPos=new int[oldColPos.length+1]; 194 System.arraycopy(oldMatrix,0,elements,0,rows[i]); 195 System.arraycopy(oldColPos,0,colPos,0,rows[i]); 196 int k; 197 for(k=rows[i];k<rows[i+1] && oldColPos[k]<j;k++) { 198 elements[k]=oldMatrix[k]; 199 colPos[k]=oldColPos[k]; 200 } 201 elements[k]=x; 202 colPos[k]=j; 203 System.arraycopy(oldMatrix,k,elements,k+1,oldMatrix.length-k); 204 System.arraycopy(oldColPos,k,colPos,k+1,oldColPos.length-k); 205 for(k=i+1;k<rows.length;k++) 206 rows[k]++; 207 } else 208 throw new MatrixDimensionException(getInvalidElementMsg(i,j)); 209 } 210 213 public double det() { 214 final AbstractDoubleSquareMatrix lu[]=this.luDecompose(null); 215 double det=lu[1].getElement(0,0); 216 for(int i=1;i<numRows;i++) 217 det*=lu[1].getElement(i,i); 218 return det*LUpivot[numRows]; 219 } 220 223 public double trace() { 224 double result=getElement(0,0); 225 for(int i=1;i<numRows;i++) 226 result+=getElement(i,i); 227 return result; 228 } 229 232 public double infNorm() { 233 double result=0.0,tmpResult; 234 for(int j,i=0;i<numRows;i++) { 235 tmpResult=0.0; 236 for(j=rows[i];j<rows[i+1];j++) 237 tmpResult+=Math.abs(elements[j]); 238 if(tmpResult>result) 239 result=tmpResult; 240 } 241 return result; 242 } 243 246 public double frobeniusNorm() { 247 double result=0.0; 248 for(int i=0;i<colPos.length;i++) 249 result+=elements[i]*elements[i]; 250 return Math.sqrt(result); 251 } 252 253 257 259 264 public AbstractDoubleSquareMatrix add(final AbstractDoubleSquareMatrix m) { 265 if(m instanceof DoubleSparseSquareMatrix) 266 return add((DoubleSparseSquareMatrix)m); 267 if(m instanceof DoubleSquareMatrix) 268 return add((DoubleSquareMatrix)m); 269 270 if(numRows==m.rows() && numCols==m.columns()) { 271 final double array[][]=new double[numRows][numCols]; 272 for(int i=0;i<numRows;i++) { 273 for(int j=rows[i];j<rows[i+1];j++) 274 array[i][colPos[j]]=elements[j]; 275 array[i][0]+=m.getElement(i,0); 276 for(int j=1;j<numCols;j++) 277 array[i][j]+=m.getElement(i,j); 278 } 279 return new DoubleSquareMatrix(array); 280 } else { 281 throw new MatrixDimensionException("Matrices are different sizes."); 282 } 283 } 284 public DoubleSquareMatrix add(final DoubleSquareMatrix m) { 285 if(numRows==m.numRows && numCols==m.numCols) { 286 final double array[][]=new double[numRows][numCols]; 287 for(int i=0;i<numRows;i++) { 288 for(int j=rows[i];j<rows[i+1];j++) 289 array[i][colPos[j]]=elements[j]; 290 array[i][0]+=m.matrix[i][0]; 291 for(int j=1;j<numCols;j++) 292 array[i][j]+=m.matrix[i][j]; 293 } 294 return new DoubleSquareMatrix(array); 295 } else 296 throw new MatrixDimensionException("Matrices are different sizes."); 297 } 298 303 public DoubleSparseSquareMatrix add(final DoubleSparseSquareMatrix m) { 304 if(numRows==m.numRows && numCols==m.numCols) { 305 DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 306 for(int i=0;i<numRows;i++) { 307 for(int j=0;j<numCols;j++) 308 ans.setElement(i,j,getElement(i,j)+m.getElement(i,j)); 309 } 310 return ans; 311 } else 312 throw new MatrixDimensionException("Matrices are different sizes."); 313 } 314 315 317 322 public AbstractDoubleSquareMatrix subtract(final AbstractDoubleSquareMatrix m) { 323 if(m instanceof DoubleSparseSquareMatrix) 324 return subtract((DoubleSparseSquareMatrix)m); 325 if(m instanceof DoubleSquareMatrix) 326 return subtract((DoubleSquareMatrix)m); 327 328 if(numRows==m.rows() && numCols==m.columns()) { 329 final double array[][]=new double[numRows][numCols]; 330 for(int i=0;i<numRows;i++) { 331 for(int j=rows[i];j<rows[i+1];j++) 332 array[i][colPos[j]]=elements[j]; 333 array[i][0]-=m.getElement(i,0); 334 for(int j=1;j<numCols;j++) 335 array[i][j]-=m.getElement(i,j); 336 } 337 return new DoubleSquareMatrix(array); 338 } else { 339 throw new MatrixDimensionException("Matrices are different sizes."); 340 } 341 } 342 public DoubleSquareMatrix subtract(final DoubleSquareMatrix m) { 343 if(numRows==m.numRows && numCols==m.numCols) { 344 final double array[][]=new double[numRows][numCols]; 345 for(int i=0;i<numRows;i++) { 346 for(int j=rows[i];j<rows[i+1];j++) 347 array[i][colPos[j]]=elements[j]; 348 array[i][0]-=m.matrix[i][0]; 349 for(int j=1;j<numCols;j++) 350 array[i][j]-=m.matrix[i][j]; 351 } 352 return new DoubleSquareMatrix(array); 353 } else 354 throw new MatrixDimensionException("Matrices are different sizes."); 355 } 356 361 public DoubleSparseSquareMatrix subtract(final DoubleSparseSquareMatrix m) { 362 if(numRows==m.numRows && numCols==m.numCols) { 363 DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 364 for(int i=0;i<numRows;i++) { 365 for(int j=0;j<numCols;j++) 366 ans.setElement(i,j,getElement(i,j)-m.getElement(i,j)); 367 } 368 return ans; 369 } else 370 throw new MatrixDimensionException("Matrices are different sizes."); 371 } 372 373 375 380 public AbstractDoubleMatrix scalarMultiply(final double x) { 381 final DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 382 ans.elements=new double[elements.length]; 383 ans.colPos=new int[colPos.length]; 384 System.arraycopy(colPos,0,ans.colPos,0,colPos.length); 385 System.arraycopy(rows,0,ans.rows,0,rows.length); 386 for(int i=0;i<colPos.length;i++) 387 ans.elements[i]=x*elements[i]; 388 return ans; 389 } 390 391 public AbstractDoubleMatrix scalarDivide(final double x) { 392 final DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 393 ans.elements=new double[elements.length]; 394 ans.colPos=new int[colPos.length]; 395 System.arraycopy(colPos,0,ans.colPos,0,colPos.length); 396 System.arraycopy(rows,0,ans.rows,0,rows.length); 397 for(int i=0;i<colPos.length;i++) 398 ans.elements[i]=elements[i]/x; 399 return ans; 400 } 401 402 404 409 public double scalarProduct(final AbstractDoubleSquareMatrix m) { 410 if(m instanceof DoubleSquareMatrix) 411 return scalarProduct((DoubleSquareMatrix)m); 412 413 if(numRows==m.numRows && numCols==m.numCols) { 414 double ans=0.0; 415 for(int i=0;i<numRows;i++) { 416 for(int j=rows[i];j<rows[i+1];j++) 417 ans+=elements[j]*m.getElement(i,colPos[j]); 418 } 419 return ans; 420 } else 421 throw new MatrixDimensionException("Matrices are different sizes."); 422 } 423 public double scalarProduct(final DoubleSquareMatrix m) { 424 if(numRows==m.numRows && numCols==m.numCols) { 425 double ans=0.0; 426 for(int i=0;i<numRows;i++) { 427 for(int j=rows[i];j<rows[i+1];j++) 428 ans+=elements[j]*m.matrix[i][colPos[j]]; 429 } 430 return ans; 431 } else 432 throw new MatrixDimensionException("Matrices are different sizes."); 433 } 434 435 437 442 public AbstractDoubleVector multiply(final AbstractDoubleVector v) { 443 if(numCols==v.dimension()) { 444 final double array[]=new double[numRows]; 445 for(int i=0;i<numRows;i++) { 446 for(int j=rows[i];j<rows[i+1];j++) 447 array[i]+=elements[j]*v.getComponent(colPos[j]); 448 } 449 return new DoubleVector(array); 450 } else 451 throw new DimensionException("Matrix and vector are incompatible."); 452 } 453 458 public AbstractDoubleSquareMatrix multiply(final AbstractDoubleSquareMatrix m) { 459 if(m instanceof DoubleSparseSquareMatrix) 460 return multiply((DoubleSparseSquareMatrix)m); 461 if(m instanceof DoubleSquareMatrix) 462 return multiply((DoubleSquareMatrix)m); 463 464 if(numCols==m.numRows) { 465 final double array[][]=new double[numRows][m.numCols]; 466 for(int j=0;j<numRows;j++) { 467 for(int k=0;k<m.numCols;k++) { 468 for(int n=rows[j];n<rows[j+1];n++) 469 array[j][k]+=elements[n]*m.getElement(colPos[n],k); 470 } 471 } 472 return new DoubleSquareMatrix(array); 473 } else 474 throw new MatrixDimensionException("Incompatible matrices."); 475 } 476 public DoubleSquareMatrix multiply(final DoubleSquareMatrix m) { 477 if(numCols==m.numRows) { 478 final double array[][]=new double[numRows][m.numCols]; 479 for(int j=0;j<numRows;j++) { 480 for(int k=0;k<m.numCols;k++) { 481 for(int n=rows[j];n<rows[j+1];n++) 482 array[j][k]+=elements[n]*m.matrix[colPos[n]][k]; 483 } 484 } 485 return new DoubleSquareMatrix(array); 486 } else 487 throw new MatrixDimensionException("Incompatible matrices."); 488 } 489 494 public DoubleSparseSquareMatrix multiply(final DoubleSparseSquareMatrix m) { 495 if(numCols==m.numRows) { 496 DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 497 for(int j=0;j<numRows;j++) { 498 for(int k=0;k<numCols;k++) { 499 double tmp=0.0; 500 for(int n=rows[j];n<rows[j+1];n++) 501 tmp+=elements[n]*m.getElement(colPos[n],k); 502 ans.setElement(j,k,tmp); 503 } 504 } 505 return ans; 506 } else 507 throw new MatrixDimensionException("Incompatible matrices."); 508 } 509 510 512 516 public Matrix transpose() { 517 final DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 518 for(int i=0;i<numRows;i++) { 519 ans.setElement(0,i,getElement(i,0)); 520 for(int j=1;j<numCols;j++) 521 ans.setElement(j,i,getElement(i,j)); 522 } 523 return ans; 524 } 525 526 528 535 public AbstractDoubleSquareMatrix[] luDecompose(int pivot[]) { 536 if(LU!=null) { 537 if(pivot!=null) 538 System.arraycopy(LUpivot,0,pivot,0,pivot.length); 539 return LU; 540 } 541 final double arrayL[][]=new double[numRows][numCols]; 542 final double arrayU[][]=new double[numRows][numCols]; 543 if(pivot==null) 544 pivot=new int[numRows+1]; 545 for(int i=0;i<numRows;i++) 546 pivot[i]=i; 547 pivot[numRows]=1; 548 for(int j=0;j<numCols;j++) { 550 for(int i=0;i<j;i++) { 551 double tmp=getElement(pivot[i],j); 552 for(int k=0;k<i;k++) 553 tmp-=arrayU[i][k]*arrayU[k][j]; 554 arrayU[i][j]=tmp; 555 } 556 double max=0.0; 557 int pivotrow=j; 558 for(int i=j;i<numRows;i++) { 559 double tmp=getElement(pivot[i],j); 560 for(int k=0;k<j;k++) 561 tmp-=arrayU[i][k]*arrayU[k][j]; 562 arrayU[i][j]=tmp; 563 tmp=Math.abs(tmp); 565 if(tmp>max) { 566 max=tmp; 567 pivotrow=i; 568 } 569 } 570 if(pivotrow!=j) { 572 double[] tmprow = arrayU[j]; 573 arrayU[j] = arrayU[pivotrow]; 574 arrayU[pivotrow] = tmprow; 575 int k=pivot[j]; 576 pivot[j]=pivot[pivotrow]; 577 pivot[pivotrow]=k; 578 pivot[numRows]=-pivot[numRows]; 580 } 581 for(int i=j+1;i<numRows;i++) 583 arrayU[i][j]/=arrayU[j][j]; 584 } 585 for(int j=0;j<numCols;j++) { 587 arrayL[j][j]=1.0; 588 for(int i=j+1;i<numRows;i++) { 589 arrayL[i][j]=arrayU[i][j]; 590 arrayU[i][j]=0.0; 591 } 592 } 593 LU=new AbstractDoubleSquareMatrix[2]; 594 LU[0]=new DoubleSquareMatrix(arrayL); 595 LU[1]=new DoubleSquareMatrix(arrayU); 596 LUpivot=new int[pivot.length]; 597 System.arraycopy(pivot,0,LUpivot,0,pivot.length); 598 return LU; 599 } 600 607 public AbstractDoubleSquareMatrix[] luDecompose() { 608 final double arrayL[][]=new double[numRows][numCols]; 609 final double arrayU[][]=new double[numRows][numCols]; 610 for(int j=0;j<numCols;j++) { 612 for(int i=0;i<j;i++) { 613 double tmp=getElement(i,j); 614 for(int k=0;k<i;k++) 615 tmp-=arrayU[i][k]*arrayU[k][j]; 616 arrayU[i][j]=tmp; 617 } 618 for(int i=j;i<numRows;i++) { 619 double tmp=getElement(i,j); 620 for(int k=0;k<j;k++) 621 tmp-=arrayU[i][k]*arrayU[k][j]; 622 arrayU[i][j]=tmp; 623 } 624 for(int i=j+1;i<numRows;i++) 626 arrayU[i][j]/=arrayU[j][j]; 627 } 628 for(int j=0;j<numCols;j++) { 630 arrayL[j][j]=1.0; 631 for(int i=j+1;i<numRows;i++) { 632 arrayL[i][j]=arrayU[i][j]; 633 arrayU[i][j]=0.0; 634 } 635 } 636 AbstractDoubleSquareMatrix[] lu=new AbstractDoubleSquareMatrix[2]; 637 lu[0]=new DoubleSquareMatrix(arrayL); 638 lu[1]=new DoubleSquareMatrix(arrayU); 639 return lu; 640 } 641 642 644 649 public AbstractDoubleSquareMatrix[] choleskyDecompose() { 650 final double arrayL[][]=new double[numRows][numCols]; 651 final double arrayU[][]=new double[numRows][numCols]; 652 arrayL[0][0]=arrayU[0][0]=Math.sqrt(getElement(0,0)); 653 for(int i=1;i<numRows;i++) 654 arrayL[i][0]=arrayU[0][i]=getElement(i,0)/arrayL[0][0]; 655 for(int j=1;j<numCols;j++) { 656 double tmp=getElement(j,j); 657 for(int i=0;i<j;i++) 658 tmp-=arrayL[j][i]*arrayL[j][i]; 659 arrayL[j][j]=arrayU[j][j]=Math.sqrt(tmp); 660 for(int i=j+1;i<numRows;i++) { 661 tmp=getElement(i,j); 662 for(int k=0;k<i;k++) 663 tmp-=arrayL[j][k]*arrayU[k][i]; 664 arrayL[i][j]=arrayU[j][i]=tmp/arrayU[j][j]; 665 } 666 } 667 final AbstractDoubleSquareMatrix lu[]=new AbstractDoubleSquareMatrix[2]; 668 lu[0]=new DoubleSquareMatrix(arrayL); 669 lu[1]=new DoubleSquareMatrix(arrayU); 670 return lu; 671 } 672 673 675 680 public AbstractDoubleMatrix mapElements(final Mapping f) { 681 final DoubleSparseSquareMatrix ans=new DoubleSparseSquareMatrix(numRows); 682 ans.elements=new double[elements.length]; 683 ans.colPos=new int[colPos.length]; 684 System.arraycopy(colPos,0,ans.colPos,0,colPos.length); 685 System.arraycopy(rows,0,ans.rows,0,rows.length); 686 for(int i=0;i<colPos.length;i++) 687 ans.elements[i]=f.map(elements[i]); 688 return ans; 689 } 690 } 691 692 | Popular Tags |