PageRenderTime 25ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/v1.6.5/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php

#
PHP | 135 lines | 70 code | 15 blank | 50 comment | 28 complexity | 8a0252db67ad0619f57564c7582e3029 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. <?php
  2. /**
  3. * @package JAMA
  4. *
  5. * Cholesky decomposition class
  6. *
  7. * For a symmetric, positive definite matrix A, the Cholesky decomposition
  8. * is an lower triangular matrix L so that A = L*L'.
  9. *
  10. * If the matrix is not symmetric or positive definite, the constructor
  11. * returns a partial decomposition and sets an internal flag that may
  12. * be queried by the isSPD() method.
  13. *
  14. * @author Paul Meagher
  15. * @author Michael Bommarito
  16. * @version 1.2
  17. */
  18. class CholeskyDecomposition {
  19. /**
  20. * Decomposition storage
  21. * @var array
  22. * @access private
  23. */
  24. var $L = array();
  25. /**
  26. * Matrix row and column dimension
  27. * @var int
  28. * @access private
  29. */
  30. var $m;
  31. /**
  32. * Symmetric positive definite flag
  33. * @var boolean
  34. * @access private
  35. */
  36. var $isspd = true;
  37. /**
  38. * CholeskyDecomposition
  39. * Class constructor - decomposes symmetric positive definite matrix
  40. * @param mixed Matrix square symmetric positive definite matrix
  41. */
  42. function CholeskyDecomposition( $A = null ) {
  43. if( is_a($A, 'Matrix') ) {
  44. $this->L = $A->getArray();
  45. $this->m = $A->getRowDimension();
  46. for( $i = 0; $i < $this->m; $i++ ) {
  47. for( $j = $i; $j < $this->m; $j++ ) {
  48. for( $sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; $k-- )
  49. $sum -= $this->L[$i][$k] * $this->L[$j][$k];
  50. if( $i == $j ) {
  51. if( $sum >= 0 ) {
  52. $this->L[$i][$i] = sqrt( $sum );
  53. } else {
  54. $this->isspd = false;
  55. }
  56. } else {
  57. if( $this->L[$i][$i] != 0 )
  58. $this->L[$j][$i] = $sum / $this->L[$i][$i];
  59. }
  60. }
  61. for ($k = $i+1; $k < $this->m; $k++)
  62. $this->L[$i][$k] = 0.0;
  63. }
  64. } else {
  65. trigger_error(ArgumentTypeException, ERROR);
  66. }
  67. }
  68. /**
  69. * Is the matrix symmetric and positive definite?
  70. * @return boolean
  71. */
  72. function isSPD () {
  73. return $this->isspd;
  74. }
  75. /**
  76. * getL
  77. * Return triangular factor.
  78. * @return Matrix Lower triangular matrix
  79. */
  80. function getL () {
  81. return new Matrix($this->L);
  82. }
  83. /**
  84. * Solve A*X = B
  85. * @param $B Row-equal matrix
  86. * @return Matrix L * L' * X = B
  87. */
  88. function solve ( $B = null ) {
  89. if( is_a($B, 'Matrix') ) {
  90. if ($B->getRowDimension() == $this->m) {
  91. if ($this->isspd) {
  92. $X = $B->getArrayCopy();
  93. $nx = $B->getColumnDimension();
  94. for ($k = 0; $k < $this->m; $k++) {
  95. for ($i = $k + 1; $i < $this->m; $i++)
  96. for ($j = 0; $j < $nx; $j++)
  97. $X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k];
  98. for ($j = 0; $j < $nx; $j++)
  99. $X[$k][$j] /= $this->L[$k][$k];
  100. }
  101. for ($k = $this->m - 1; $k >= 0; $k--) {
  102. for ($j = 0; $j < $nx; $j++)
  103. $X[$k][$j] /= $this->L[$k][$k];
  104. for ($i = 0; $i < $k; $i++)
  105. for ($j = 0; $j < $nx; $j++)
  106. $X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i];
  107. }
  108. return new Matrix($X, $this->m, $nx);
  109. } else {
  110. trigger_error(MatrixSPDException, ERROR);
  111. }
  112. } else {
  113. trigger_error(MatrixDimensionException, ERROR);
  114. }
  115. } else {
  116. trigger_error(ArgumentTypeException, ERROR);
  117. }
  118. }
  119. }
  120. ?>