1 9 package org.jscience.mathematics.vectors; 10 11 import java.util.Comparator ; 12 13 import org.jscience.mathematics.structures.Field; 14 import org.jscience.mathematics.numbers.Number; 15 16 import javolution.context.LocalContext; 17 import javolution.context.RealtimeObject; 18 import javolution.util.FastTable; 19 import javolution.util.Index; 20 21 47 public final class LUDecomposition<F extends Field<F>> extends RealtimeObject { 48 49 52 public static final Comparator <Field> NUMERIC_COMPARATOR = new Comparator <Field>() { 53 54 @SuppressWarnings ("unchecked") 55 public int compare(Field left, Field right) { 56 if ((left instanceof Number ) && (right instanceof Number )) 57 return ((Number ) left).isLargerThan((Number ) right) ? 1 : -1; 58 if (left.equals(left.plus(left))) return -1; 60 if (right.equals(right.plus(right))) return 1; 62 return 0; 63 } 64 }; 65 66 69 private static final LocalContext.Reference<Comparator <Field>> PIVOT_COMPARATOR = new LocalContext.Reference<Comparator <Field>>( 70 NUMERIC_COMPARATOR); 71 72 75 private int _n; 76 77 80 private final FastTable<Index> _pivots = new FastTable<Index>(); 81 82 85 private DenseMatrix<F> _LU; 86 87 90 private int _permutationCount; 91 92 99 @SuppressWarnings ("unchecked") 100 public static <F extends Field<F>> LUDecomposition<F> valueOf( 101 Matrix<F> source) { 102 if (!source.isSquare()) 103 throw new DimensionException("Matrix is not square"); 104 int dimension = source.getNumberOfRows(); 105 LUDecomposition lu = FACTORY.object(); 106 lu._n = dimension; 107 lu._permutationCount = 0; 108 lu.construct(source); 109 return lu; 110 } 111 112 120 private void construct(Matrix<F> source) { 121 _LU = source instanceof DenseMatrix ? ((DenseMatrix<F>) source).copy() 122 : DenseMatrix.valueOf(source); 123 _pivots.clear(); 124 for (int i = 0; i < _n; i++) { 125 _pivots.add(Index.valueOf(i)); 126 } 127 128 Comparator <Field> cmp = LUDecomposition.getPivotComparator(); 130 final int n = _n; 131 for (int k = 0; k < _n; k++) { 132 133 if (cmp != null) { int pivot = k; 138 for (int i = k + 1; i < n; i++) { 139 if (cmp.compare(_LU.get(i, k), _LU.get(pivot, k)) > 0) { 140 pivot = i; 141 } 142 } 143 if (pivot != k) { for (int j = 0; j < n; j++) { 145 F tmp = _LU.get(pivot, j); 146 _LU.set(pivot, j, _LU.get(k, j)); 147 _LU.set(k, j, tmp); 148 } 149 int j = _pivots.get(pivot).intValue(); 150 _pivots.set(pivot, _pivots.get(k)); 151 _pivots.set(k, Index.valueOf(j)); 152 _permutationCount++; 153 } 154 } 155 156 F lukkInv = _LU.get(k, k).inverse(); 158 for (int i = k + 1; i < n; i++) { 159 _LU.set(i, k, _LU.get(i, k).times(lukkInv)); 162 for (int j = k + 1; j < n; j++) { 163 _LU.set(i, j, _LU.get(i, j).plus( 164 _LU.get(i, k).times(_LU.get(k, j).opposite()))); 165 } 166 } 167 } 168 } 169 170 176 public static void setPivotComparator(Comparator <Field> cmp) { 177 PIVOT_COMPARATOR.set(cmp); 178 } 179 180 187 public static Comparator <Field> getPivotComparator() { 188 return PIVOT_COMPARATOR.get(); 189 } 190 191 199 public DenseMatrix<F> solve(Matrix<F> B) { 200 if (_n != B.getNumberOfRows()) 201 throw new DimensionException("Input vector has " 202 + B.getNumberOfRows() + " rows instead of " + _n); 203 204 final int n = B.getNumberOfColumns(); 206 DenseMatrix<F> X = createNullDenseMatrix(_n, n); 207 for (int i = 0; i < _n; i++) { 208 for (int j = 0; j < n; j++) { 209 X.set(i, j, B.get(_pivots.get(i).intValue(), j)); 210 } 211 } 212 213 for (int k = 0; k < _n; k++) { 215 for (int i = k + 1; i < _n; i++) { 216 F luik = _LU.get(i, k); 217 for (int j = 0; j < n; j++) { 218 X.set(i, j, X.get(i, j).plus( 219 luik.times(X.get(k, j).opposite()))); 220 } 221 } 222 } 223 224 for (int k = _n - 1; k >= 0; k--) { 226 for (int j = 0; j < n; j++) { 227 X.set(k, j, (_LU.get(k, k).inverse()).times(X.get(k, j))); 228 } 229 for (int i = 0; i < k; i++) { 230 F luik = _LU.get(i, k); 231 for (int j = 0; j < n; j++) { 232 X.set(i, j, X.get(i, j).plus( 233 luik.times(X.get(k, j).opposite()))); 234 } 235 } 236 } 237 return X; 238 } 239 240 private DenseMatrix<F> createNullDenseMatrix(int m, int n) { 241 DenseMatrix<F> M = DenseMatrix.newInstance(n, false); 242 for (int i = 0; i < m; i++) { 243 DenseVector<F> V = DenseVector.newInstance(); 244 M._rows.add(V); 245 for (int j = 0; j < n; j++) { 246 V._elements.add(null); 247 } 248 } 249 return M; 250 } 251 252 258 public DenseMatrix<F> inverse() { 259 final int n = _n; 261 DenseMatrix<F> R = createNullDenseMatrix(n, n); 262 for (int i = 0; i < n; i++) { 263 for (int j = i; j < n; j++) { 264 R.set(i, j, _LU.get(i, j)); 265 } 266 } 267 for (int j = n - 1; j >= 0; j--) { 268 R.set(j, j, R.get(j, j).inverse()); 269 for (int i = j - 1; i >= 0; i--) { 270 F sum = R.get(i, j).times(R.get(j, j).opposite()); 271 for (int k = j - 1; k > i; k--) { 272 sum = sum.plus(R.get(i, k).times(R.get(k, j).opposite())); 273 } 274 R.set(i, j, (R.get(i, i).inverse()).times(sum)); 275 } 276 } 277 for (int i = 0; i < n; i++) { 279 for (int j = n - 2; j >= 0; j--) { 280 for (int k = j + 1; k < n; k++) { 281 F lukj = _LU.get(k, j); 282 if (R.get(i, j) != null) { 283 R.set(i, j, R.get(i, j).plus( 284 R.get(i, k).times(lukj.opposite()))); 285 } else { 286 R.set(i, j, R.get(i, k).times(lukj.opposite())); 287 } 288 } 289 } 290 } 291 FastTable<F> tmp = FastTable.newInstance(); 293 for (int i = 0; i < n; i++) { 294 tmp.reset(); 295 for (int j = 0; j < n; j++) { 296 tmp.add(R.get(i, j)); 297 } 298 for (int j = 0; j < n; j++) { 299 R.set(i, _pivots.get(j).intValue(), tmp.get(j)); 300 } 301 } 302 FastTable.recycle(tmp); 303 return R; 304 } 305 306 312 public F determinant() { 313 F product = _LU.get(0, 0); 314 for (int i = 1; i < _n; i++) { 315 product = product.times(_LU.get(i, i)); 316 } 317 return ((_permutationCount & 1) == 0) ? product : product.opposite(); 318 } 319 320 328 public DenseMatrix<F> getLower(F zero, F one) { 329 DenseMatrix<F> L = _LU.copy(); 330 for (int j = 0; j < _n; j++) { 331 for (int i = 0; i < j; i++) { 332 L.set(i, j, zero); 333 } 334 L.set(j, j, one); 335 } 336 return L; 337 } 338 339 345 public DenseMatrix<F> getUpper(F zero) { 346 DenseMatrix<F> U = _LU.copy(); 347 for (int j = 0; j < _n; j++) { 348 for (int i = j + 1; i < _n; i++) { 349 U.set(i, j, zero); 350 } 351 } 352 return U; 353 } 354 355 362 public SparseMatrix<F> getPermutation(F zero, F one) { 363 SparseMatrix<F> P = SparseMatrix.newInstance(_n, zero, false); 364 for (int i = 0; i < _n; i++) { 365 P.getRow(_pivots.get(i).intValue())._elements.put(Index.valueOf(i), 366 one); 367 } 368 return P; 369 } 370 371 376 public DenseMatrix<F> getLU() { 377 return _LU; 378 } 379 380 385 public FastTable<Index> getPivots() { 386 return _pivots; 387 } 388 389 @Override 390 public boolean move(ObjectSpace os) { 391 if (super.move(os)) { 392 _LU.move(os); 393 return true; 394 } 395 return false; 396 } 397 398 402 private static final Factory<LUDecomposition> FACTORY = new Factory<LUDecomposition>() { 403 protected LUDecomposition create() { 404 return new LUDecomposition(); 405 } 406 407 @SuppressWarnings ("unchecked") 408 protected void cleanup(LUDecomposition lu) { 409 lu._LU = null; 410 } 411 }; 412 413 private LUDecomposition() { 414 } 415 416 } | Popular Tags |