lsolveAll.js (6125B)
1 "use strict"; 2 3 var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 5 Object.defineProperty(exports, "__esModule", { 6 value: true 7 }); 8 exports.createLsolveAll = void 0; 9 10 var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); 11 12 var _factory = require("../../../utils/factory.js"); 13 14 var _solveValidation = require("./utils/solveValidation.js"); 15 16 var name = 'lsolveAll'; 17 var dependencies = ['typed', 'matrix', 'divideScalar', 'multiplyScalar', 'subtract', 'equalScalar', 'DenseMatrix']; 18 var createLsolveAll = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 19 var typed = _ref.typed, 20 matrix = _ref.matrix, 21 divideScalar = _ref.divideScalar, 22 multiplyScalar = _ref.multiplyScalar, 23 subtract = _ref.subtract, 24 equalScalar = _ref.equalScalar, 25 DenseMatrix = _ref.DenseMatrix; 26 var solveValidation = (0, _solveValidation.createSolveValidation)({ 27 DenseMatrix: DenseMatrix 28 }); 29 /** 30 * Finds all solutions of a linear equation system by forwards substitution. Matrix must be a lower triangular matrix. 31 * 32 * `L * x = b` 33 * 34 * Syntax: 35 * 36 * math.lsolveAll(L, b) 37 * 38 * Examples: 39 * 40 * const a = [[-2, 3], [2, 1]] 41 * const b = [11, 9] 42 * const x = lsolveAll(a, b) // [ [[-5.5], [20]] ] 43 * 44 * See also: 45 * 46 * lsolve, lup, slu, usolve, lusolve 47 * 48 * @param {Matrix, Array} L A N x N matrix or array (L) 49 * @param {Matrix, Array} b A column vector with the b values 50 * 51 * @return {DenseMatrix[] | Array[]} An array of affine-independent column vectors (x) that solve the linear system 52 */ 53 54 return typed(name, { 55 'SparseMatrix, Array | Matrix': function SparseMatrixArrayMatrix(m, b) { 56 return _sparseForwardSubstitution(m, b); 57 }, 58 'DenseMatrix, Array | Matrix': function DenseMatrixArrayMatrix(m, b) { 59 return _denseForwardSubstitution(m, b); 60 }, 61 'Array, Array | Matrix': function ArrayArrayMatrix(a, b) { 62 var m = matrix(a); 63 64 var R = _denseForwardSubstitution(m, b); 65 66 return R.map(function (r) { 67 return r.valueOf(); 68 }); 69 } 70 }); 71 72 function _denseForwardSubstitution(m, b_) { 73 // the algorithm is derived from 74 // https://www.overleaf.com/read/csvgqdxggyjv 75 // array of right-hand sides 76 var B = [solveValidation(m, b_, true)._data.map(function (e) { 77 return e[0]; 78 })]; 79 var M = m._data; 80 var rows = m._size[0]; 81 var columns = m._size[1]; // loop columns 82 83 for (var i = 0; i < columns; i++) { 84 var L = B.length; // loop right-hand sides 85 86 for (var k = 0; k < L; k++) { 87 var b = B[k]; 88 89 if (!equalScalar(M[i][i], 0)) { 90 // non-singular row 91 b[i] = divideScalar(b[i], M[i][i]); 92 93 for (var j = i + 1; j < columns; j++) { 94 // b[j] -= b[i] * M[j,i] 95 b[j] = subtract(b[j], multiplyScalar(b[i], M[j][i])); 96 } 97 } else if (!equalScalar(b[i], 0)) { 98 // singular row, nonzero RHS 99 if (k === 0) { 100 // There is no valid solution 101 return []; 102 } else { 103 // This RHS is invalid but other solutions may still exist 104 B.splice(k, 1); 105 k -= 1; 106 L -= 1; 107 } 108 } else if (k === 0) { 109 // singular row, RHS is zero 110 var bNew = (0, _toConsumableArray2.default)(b); 111 bNew[i] = 1; 112 113 for (var _j = i + 1; _j < columns; _j++) { 114 bNew[_j] = subtract(bNew[_j], M[_j][i]); 115 } 116 117 B.push(bNew); 118 } 119 } 120 } 121 122 return B.map(function (x) { 123 return new DenseMatrix({ 124 data: x.map(function (e) { 125 return [e]; 126 }), 127 size: [rows, 1] 128 }); 129 }); 130 } 131 132 function _sparseForwardSubstitution(m, b_) { 133 // array of right-hand sides 134 var B = [solveValidation(m, b_, true)._data.map(function (e) { 135 return e[0]; 136 })]; 137 var rows = m._size[0]; 138 var columns = m._size[1]; 139 var values = m._values; 140 var index = m._index; 141 var ptr = m._ptr; // loop columns 142 143 for (var i = 0; i < columns; i++) { 144 var L = B.length; // loop right-hand sides 145 146 for (var k = 0; k < L; k++) { 147 var b = B[k]; // values & indices (column i) 148 149 var iValues = []; 150 var iIndices = []; // first & last indeces in column 151 152 var firstIndex = ptr[i]; 153 var lastIndex = ptr[i + 1]; // find the value at [i, i] 154 155 var Mii = 0; 156 157 for (var j = firstIndex; j < lastIndex; j++) { 158 var J = index[j]; // check row 159 160 if (J === i) { 161 Mii = values[j]; 162 } else if (J > i) { 163 // store lower triangular 164 iValues.push(values[j]); 165 iIndices.push(J); 166 } 167 } 168 169 if (!equalScalar(Mii, 0)) { 170 // non-singular row 171 b[i] = divideScalar(b[i], Mii); 172 173 for (var _j2 = 0, _lastIndex = iIndices.length; _j2 < _lastIndex; _j2++) { 174 var _J = iIndices[_j2]; 175 b[_J] = subtract(b[_J], multiplyScalar(b[i], iValues[_j2])); 176 } 177 } else if (!equalScalar(b[i], 0)) { 178 // singular row, nonzero RHS 179 if (k === 0) { 180 // There is no valid solution 181 return []; 182 } else { 183 // This RHS is invalid but other solutions may still exist 184 B.splice(k, 1); 185 k -= 1; 186 L -= 1; 187 } 188 } else if (k === 0) { 189 // singular row, RHS is zero 190 var bNew = (0, _toConsumableArray2.default)(b); 191 bNew[i] = 1; 192 193 for (var _j3 = 0, _lastIndex2 = iIndices.length; _j3 < _lastIndex2; _j3++) { 194 var _J2 = iIndices[_j3]; 195 bNew[_J2] = subtract(bNew[_J2], iValues[_j3]); 196 } 197 198 B.push(bNew); 199 } 200 } 201 } 202 203 return B.map(function (x) { 204 return new DenseMatrix({ 205 data: x.map(function (e) { 206 return [e]; 207 }), 208 size: [rows, 1] 209 }); 210 }); 211 } 212 }); 213 exports.createLsolveAll = createLsolveAll;