usolveAll.js (6202B)
1 "use strict"; 2 3 var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 5 Object.defineProperty(exports, "__esModule", { 6 value: true 7 }); 8 exports.createUsolveAll = 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 = 'usolveAll'; 17 var dependencies = ['typed', 'matrix', 'divideScalar', 'multiplyScalar', 'subtract', 'equalScalar', 'DenseMatrix']; 18 var createUsolveAll = /* #__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 backward substitution. Matrix must be an upper triangular matrix. 31 * 32 * `U * x = b` 33 * 34 * Syntax: 35 * 36 * math.usolveAll(U, b) 37 * 38 * Examples: 39 * 40 * const a = [[-2, 3], [2, 1]] 41 * const b = [11, 9] 42 * const x = usolveAll(a, b) // [ [[8], [9]] ] 43 * 44 * See also: 45 * 46 * usolve, lup, slu, usolve, lusolve 47 * 48 * @param {Matrix, Array} U A N x N matrix or array (U) 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 _sparseBackwardSubstitution(m, b); 57 }, 58 'DenseMatrix, Array | Matrix': function DenseMatrixArrayMatrix(m, b) { 59 return _denseBackwardSubstitution(m, b); 60 }, 61 'Array, Array | Matrix': function ArrayArrayMatrix(a, b) { 62 var m = matrix(a); 63 64 var R = _denseBackwardSubstitution(m, b); 65 66 return R.map(function (r) { 67 return r.valueOf(); 68 }); 69 } 70 }); 71 72 function _denseBackwardSubstitution(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 backwards 82 83 for (var i = columns - 1; i >= 0; 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 >= 0; 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 >= 0; _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 _sparseBackwardSubstitution(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 backwards 142 143 for (var i = columns - 1; i >= 0; 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 = lastIndex - 1; j >= firstIndex; j--) { 158 var J = index[j]; // check row 159 160 if (J === i) { 161 Mii = values[j]; 162 } else if (J < i) { 163 // store upper 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); // loop upper triangular 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; // loop upper triangular 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.createUsolveAll = createUsolveAll;