csLu.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createCsLu = void 0;
  6. var _factory = require("../../../utils/factory.js");
  7. var _csSpsolve = require("./csSpsolve.js");
  8. var name = 'csLu';
  9. var dependencies = ['abs', 'divideScalar', 'multiply', 'subtract', 'larger', 'largerEq', 'SparseMatrix'];
  10. var createCsLu = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  11. var abs = _ref.abs,
  12. divideScalar = _ref.divideScalar,
  13. multiply = _ref.multiply,
  14. subtract = _ref.subtract,
  15. larger = _ref.larger,
  16. largerEq = _ref.largerEq,
  17. SparseMatrix = _ref.SparseMatrix;
  18. var csSpsolve = (0, _csSpsolve.createCsSpsolve)({
  19. divideScalar: divideScalar,
  20. multiply: multiply,
  21. subtract: subtract
  22. });
  23. /**
  24. * Computes the numeric LU factorization of the sparse matrix A. Implements a Left-looking LU factorization
  25. * algorithm that computes L and U one column at a tume. At the kth step, it access columns 1 to k-1 of L
  26. * and column k of A. Given the fill-reducing column ordering q (see parameter s) computes L, U and pinv so
  27. * L * U = A(p, q), where p is the inverse of pinv.
  28. *
  29. * @param {Matrix} m The A Matrix to factorize
  30. * @param {Object} s The symbolic analysis from csSqr(). Provides the fill-reducing
  31. * column ordering q
  32. * @param {Number} tol Partial pivoting threshold (1 for partial pivoting)
  33. *
  34. * @return {Number} The numeric LU factorization of A or null
  35. *
  36. * Reference: http://faculty.cse.tamu.edu/davis/publications.html
  37. */
  38. return function csLu(m, s, tol) {
  39. // validate input
  40. if (!m) {
  41. return null;
  42. }
  43. // m arrays
  44. var size = m._size;
  45. // columns
  46. var n = size[1];
  47. // symbolic analysis result
  48. var q;
  49. var lnz = 100;
  50. var unz = 100;
  51. // update symbolic analysis parameters
  52. if (s) {
  53. q = s.q;
  54. lnz = s.lnz || lnz;
  55. unz = s.unz || unz;
  56. }
  57. // L arrays
  58. var lvalues = []; // (lnz)
  59. var lindex = []; // (lnz)
  60. var lptr = []; // (n + 1)
  61. // L
  62. var L = new SparseMatrix({
  63. values: lvalues,
  64. index: lindex,
  65. ptr: lptr,
  66. size: [n, n]
  67. });
  68. // U arrays
  69. var uvalues = []; // (unz)
  70. var uindex = []; // (unz)
  71. var uptr = []; // (n + 1)
  72. // U
  73. var U = new SparseMatrix({
  74. values: uvalues,
  75. index: uindex,
  76. ptr: uptr,
  77. size: [n, n]
  78. });
  79. // inverse of permutation vector
  80. var pinv = []; // (n)
  81. // vars
  82. var i, p;
  83. // allocate arrays
  84. var x = []; // (n)
  85. var xi = []; // (2 * n)
  86. // initialize variables
  87. for (i = 0; i < n; i++) {
  88. // clear workspace
  89. x[i] = 0;
  90. // no rows pivotal yet
  91. pinv[i] = -1;
  92. // no cols of L yet
  93. lptr[i + 1] = 0;
  94. }
  95. // reset number of nonzero elements in L and U
  96. lnz = 0;
  97. unz = 0;
  98. // compute L(:,k) and U(:,k)
  99. for (var k = 0; k < n; k++) {
  100. // update ptr
  101. lptr[k] = lnz;
  102. uptr[k] = unz;
  103. // apply column permutations if needed
  104. var col = q ? q[k] : k;
  105. // solve triangular system, x = L\A(:,col)
  106. var top = csSpsolve(L, m, col, xi, x, pinv, 1);
  107. // find pivot
  108. var ipiv = -1;
  109. var a = -1;
  110. // loop xi[] from top -> n
  111. for (p = top; p < n; p++) {
  112. // x[i] is nonzero
  113. i = xi[p];
  114. // check row i is not yet pivotal
  115. if (pinv[i] < 0) {
  116. // absolute value of x[i]
  117. var xabs = abs(x[i]);
  118. // check absoulte value is greater than pivot value
  119. if (larger(xabs, a)) {
  120. // largest pivot candidate so far
  121. a = xabs;
  122. ipiv = i;
  123. }
  124. } else {
  125. // x(i) is the entry U(pinv[i],k)
  126. uindex[unz] = pinv[i];
  127. uvalues[unz++] = x[i];
  128. }
  129. }
  130. // validate we found a valid pivot
  131. if (ipiv === -1 || a <= 0) {
  132. return null;
  133. }
  134. // update actual pivot column, give preference to diagonal value
  135. if (pinv[col] < 0 && largerEq(abs(x[col]), multiply(a, tol))) {
  136. ipiv = col;
  137. }
  138. // the chosen pivot
  139. var pivot = x[ipiv];
  140. // last entry in U(:,k) is U(k,k)
  141. uindex[unz] = k;
  142. uvalues[unz++] = pivot;
  143. // ipiv is the kth pivot row
  144. pinv[ipiv] = k;
  145. // first entry in L(:,k) is L(k,k) = 1
  146. lindex[lnz] = ipiv;
  147. lvalues[lnz++] = 1;
  148. // L(k+1:n,k) = x / pivot
  149. for (p = top; p < n; p++) {
  150. // row
  151. i = xi[p];
  152. // check x(i) is an entry in L(:,k)
  153. if (pinv[i] < 0) {
  154. // save unpermuted row in L
  155. lindex[lnz] = i;
  156. // scale pivot column
  157. lvalues[lnz++] = divideScalar(x[i], pivot);
  158. }
  159. // x[0..n-1] = 0 for next k
  160. x[i] = 0;
  161. }
  162. }
  163. // update ptr
  164. lptr[n] = lnz;
  165. uptr[n] = unz;
  166. // fix row indices of L for final pinv
  167. for (p = 0; p < lnz; p++) {
  168. lindex[p] = pinv[lindex[p]];
  169. }
  170. // trim arrays
  171. lvalues.splice(lnz, lvalues.length - lnz);
  172. lindex.splice(lnz, lindex.length - lnz);
  173. uvalues.splice(unz, uvalues.length - unz);
  174. uindex.splice(unz, uindex.length - unz);
  175. // return LU factor
  176. return {
  177. L: L,
  178. U: U,
  179. pinv: pinv
  180. };
  181. };
  182. });
  183. exports.createCsLu = createCsLu;