JAMA

# Source for file LUDecomposition.php

Documentation is available at LUDecomposition.php

1. <?php
2. /**
3. * @package JAMA
4. *
5. * For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
6. * unit lower triangular matrix L, an n-by-n upper triangular matrix U,
7. * and a permutation vector piv of length m so that A(piv,:) = L*U.
8. * If m < n, then L is m-by-m and U is m-by-n.
9. *
10. * The LU decompostion with pivoting always exists, even if the matrix is
11. * singular, so the constructor will never fail. The primary use of the
12. * LU decomposition is in the solution of square systems of simultaneous
13. * linear equations. This will fail if isNonsingular() returns false.
14. *
15. * @author Paul Meagher
16. * @author Bartosz Matosiuk
17. * @author Michael Bommarito
18. * @version 1.1
19. * @license PHP v3.0
20. */
21. class PHPExcel_Shared_JAMA_LUDecomposition {
23. const MatrixSingularException = "Can only perform operation on singular matrix.";
24. const MatrixSquareException = "Mismatched Row dimension";
26. /**
27. * Decomposition storage
28. * @var array
29. */
30. private $LU = array();
32. /**
33. * Row dimension.
34. * @var int
35. */
36. private $m;
38. /**
39. * Column dimension.
40. * @var int
41. */
42. private $n;
44. /**
45. * Pivot sign.
46. * @var int
47. */
48. private $pivsign;
50. /**
51. * Internal storage of pivot vector.
52. * @var array
53. */
54. private $piv = array();
57. /**
58. * LU Decomposition constructor.
59. *
60. * @param $A Rectangular matrix
61. * @return Structure to access L, U and piv.
62. */
63. public function __construct ($A) {
64. if ($A instanceof PHPExcel_Shared_JAMA_Matrix ) {
65. // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
66. $this->LU = $A->getArray();
67. $this->m = $A->getRowDimension();
68. $this->n = $A->getColumnDimension();
69. for ($i = 0; $i < $this->m; ++$i) {
70. $this->piv[$i] = $i;
71. }
72. $this->pivsign = 1;
73. $LUrowi = $LUcolj = array();
75. // Outer loop.
76. for ($j = 0; $j < $this->n; ++$j) {
77. // Make a copy of the j-th column to localize references.
78. for ($i = 0; $i < $this->m; ++$i) {
79. $LUcolj[$i] = &$this->LU[$i][$j];
80. }
81. // Apply previous transformations.
82. for ($i = 0; $i < $this->m; ++$i) {
83. $LUrowi = $this->LU[$i];
84. // Most of the time is spent in the following dot product.
85. $kmax = min ($i,$j);
86. $s = 0.0;
87. for ($k = 0; $k < $kmax; ++$k) {
88. $s += $LUrowi[$k] * $LUcolj[$k];
89. }
90. $LUrowi[$j] = $LUcolj[$i] -= $s;
91. }
92. // Find pivot and exchange if necessary.
93. $p = $j;
94. for ($i = $j+1; $i < $this->m; ++$i) {
95. if ( abs ($LUcolj[$i]) > abs ($LUcolj[$p])) {
96. $p = $i;
97. }
98. }
99. if ($p != $j) {
100. for ($k = 0; $k < $this->n; ++$k) {
101. $t = $this->LU[$p][$k];
102. $this->LU[$p][$k] = $this->LU[$j][$k];
103. $this->LU[$j][$k] = $t;
104. }
105. $k = $this->piv[$p];
106. $this->piv[$p] = $this->piv[$j];
107. $this->piv[$j] = $k;
108. $this->pivsign = $this->pivsign * -1;
109. }
110. // Compute multipliers.
111. if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) {
112. for ($i = $j+1; $i < $this->m; ++$i) {
113. $this->LU[$i][$j] /= $this->LU[$j][$j];
114. }
115. }
116. }
117. } else {
118. throw new Exception( PHPExcel_Shared_JAMA_Matrix ::ArgumentTypeException);
119. }
120. } // function __construct()
123. /**
124. * Get lower triangular factor.
125. *
126. * @return array Lower triangular factor
127. */
128. public function getL () {
129. for ($i = 0; $i < $this->m; ++$i) {
130. for ($j = 0; $j < $this->n; ++$j) {
131. if ($i > $j) {
132. $L[$i][$j] = $this->LU[$i][$j];
133. } elseif ($i == $j) {
134. $L[$i][$j] = 1.0;
135. } else {
136. $L[$i][$j] = 0.0;
137. }
138. }
139. }
140. return new PHPExcel_Shared_JAMA_Matrix ($L);
141. } // function getL()
144. /**
145. * Get upper triangular factor.
146. *
147. * @return array Upper triangular factor
148. */
149. public function getU () {
150. for ($i = 0; $i < $this->n; ++$i) {
151. for ($j = 0; $j < $this->n; ++$j) {
152. if ($i <= $j) {
153. $U[$i][$j] = $this->LU[$i][$j];
154. } else {
155. $U[$i][$j] = 0.0;
156. }
157. }
158. }
159. return new PHPExcel_Shared_JAMA_Matrix ($U);
160. } // function getU()
163. /**
164. * Return pivot permutation vector.
165. *
166. * @return array Pivot vector
167. */
168. public function getPivot () {
169. return $this->piv;
170. } // function getPivot()
173. /**
174. * Alias for getPivot
175. *
176. * @see getPivot
177. */
178. public function getDoublePivot () {
179. return $this-> getPivot ();
180. } // function getDoublePivot()
183. /**
184. * Is the matrix nonsingular?
185. *
186. * @return true if U, and hence A, is nonsingular.
187. */
188. public function isNonsingular () {
189. for ($j = 0; $j < $this->n; ++$j) {
190. if ($this->LU[$j][$j] == 0) {
191. return false;
192. }
193. }
194. return true;
195. } // function isNonsingular()
198. /**
199. * Count determinants
200. *
201. * @return array d matrix deterninat
202. */
203. public function det () {
204. if ($this->m == $this->n) {
205. $d = $this->pivsign;
206. for ($j = 0; $j < $this->n; ++$j) {
207. $d *= $this->LU[$j][$j];
208. }
209. return $d;
210. } else {
211. throw new Exception( PHPExcel_Shared_JAMA_Matrix ::MatrixDimensionException);
212. }
213. } // function det()
216. /**
217. * Solve A*X = B
218. *
219. * @param $B A Matrix with as many rows as A and any number of columns.
220. * @return X so that L*U*X = B(piv,:)
221. * @exception IllegalArgumentException Matrix row dimensions must agree.
222. * @exception RuntimeException Matrix is singular.
223. */
224. public function solve ($B) {
225. if ($B->getRowDimension() == $this->m) {
226. if ($this-> isNonsingular ()) {
227. // Copy right hand side with pivoting
228. $nx = $B->getColumnDimension();
229. $X = $B->getMatrix($this->piv, 0, $nx-1);
230. // Solve L*Y = B(piv,:)
231. for ($k = 0; $k < $this->n; ++$k) {
232. for ($i = $k+1; $i < $this->n; ++$i) {
233. for ($j = 0; $j < $nx; ++$j) {
234. $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
235. }
236. }
237. }
238. // Solve U*X = Y;
239. for ($k = $this->n-1; $k >= 0; --$k) {
240. for ($j = 0; $j < $nx; ++$j) {
241. $X->A[$k][$j] /= $this->LU[$k][$k];
242. }
243. for ($i = 0; $i < $k; ++$i) {
244. for ($j = 0; $j < $nx; ++$j) {
245. $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
246. }
247. }
248. }
249. return $X;
250. } else {
251. throw new Exception(self::MatrixSingularException);
252. }
253. } else {
254. throw new Exception(self::MatrixSquareException);
255. }
256. } // function solve()
258. } // class PHPExcel_Shared_JAMA_LUDecomposition

Documentation generated on Fri, 12 Oct 2012 00:16:40 +0200 by phpDocumentor 1.4.4