usolve.js (4486B)
1 import { factory } from '../../../utils/factory.js'; 2 import { createSolveValidation } from './utils/solveValidation.js'; 3 var name = 'usolve'; 4 var dependencies = ['typed', 'matrix', 'divideScalar', 'multiplyScalar', 'subtract', 'equalScalar', 'DenseMatrix']; 5 export var createUsolve = /* #__PURE__ */factory(name, dependencies, _ref => { 6 var { 7 typed, 8 matrix, 9 divideScalar, 10 multiplyScalar, 11 subtract, 12 equalScalar, 13 DenseMatrix 14 } = _ref; 15 var solveValidation = createSolveValidation({ 16 DenseMatrix 17 }); 18 /** 19 * Finds one solution of a linear equation system by backward substitution. Matrix must be an upper triangular matrix. Throws an error if there's no solution. 20 * 21 * `U * x = b` 22 * 23 * Syntax: 24 * 25 * math.usolve(U, b) 26 * 27 * Examples: 28 * 29 * const a = [[-2, 3], [2, 1]] 30 * const b = [11, 9] 31 * const x = usolve(a, b) // [[8], [9]] 32 * 33 * See also: 34 * 35 * usolveAll, lup, slu, usolve, lusolve 36 * 37 * @param {Matrix, Array} U A N x N matrix or array (U) 38 * @param {Matrix, Array} b A column vector with the b values 39 * 40 * @return {DenseMatrix | Array} A column vector with the linear system solution (x) 41 */ 42 43 return typed(name, { 44 'SparseMatrix, Array | Matrix': function SparseMatrixArrayMatrix(m, b) { 45 return _sparseBackwardSubstitution(m, b); 46 }, 47 'DenseMatrix, Array | Matrix': function DenseMatrixArrayMatrix(m, b) { 48 return _denseBackwardSubstitution(m, b); 49 }, 50 'Array, Array | Matrix': function ArrayArrayMatrix(a, b) { 51 var m = matrix(a); 52 53 var r = _denseBackwardSubstitution(m, b); 54 55 return r.valueOf(); 56 } 57 }); 58 59 function _denseBackwardSubstitution(m, b) { 60 // make b into a column vector 61 b = solveValidation(m, b, true); 62 var bdata = b._data; 63 var rows = m._size[0]; 64 var columns = m._size[1]; // result 65 66 var x = []; 67 var mdata = m._data; // loop columns backwards 68 69 for (var j = columns - 1; j >= 0; j--) { 70 // b[j] 71 var bj = bdata[j][0] || 0; // x[j] 72 73 var xj = void 0; 74 75 if (!equalScalar(bj, 0)) { 76 // value at [j, j] 77 var vjj = mdata[j][j]; 78 79 if (equalScalar(vjj, 0)) { 80 // system cannot be solved 81 throw new Error('Linear system cannot be solved since matrix is singular'); 82 } 83 84 xj = divideScalar(bj, vjj); // loop rows 85 86 for (var i = j - 1; i >= 0; i--) { 87 // update copy of b 88 bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))]; 89 } 90 } else { 91 // zero value at j 92 xj = 0; 93 } // update x 94 95 96 x[j] = [xj]; 97 } 98 99 return new DenseMatrix({ 100 data: x, 101 size: [rows, 1] 102 }); 103 } 104 105 function _sparseBackwardSubstitution(m, b) { 106 // make b into a column vector 107 b = solveValidation(m, b, true); 108 var bdata = b._data; 109 var rows = m._size[0]; 110 var columns = m._size[1]; 111 var values = m._values; 112 var index = m._index; 113 var ptr = m._ptr; // result 114 115 var x = []; // loop columns backwards 116 117 for (var j = columns - 1; j >= 0; j--) { 118 var bj = bdata[j][0] || 0; 119 120 if (!equalScalar(bj, 0)) { 121 // non-degenerate row, find solution 122 var vjj = 0; // upper triangular matrix values & index (column j) 123 124 var jValues = []; 125 var jIndices = []; // first & last indeces in column 126 127 var firstIndex = ptr[j]; 128 var lastIndex = ptr[j + 1]; // values in column, find value at [j, j], loop backwards 129 130 for (var k = lastIndex - 1; k >= firstIndex; k--) { 131 var i = index[k]; // check row (rows are not sorted!) 132 133 if (i === j) { 134 vjj = values[k]; 135 } else if (i < j) { 136 // store upper triangular 137 jValues.push(values[k]); 138 jIndices.push(i); 139 } 140 } // at this point we must have a value in vjj 141 142 143 if (equalScalar(vjj, 0)) { 144 throw new Error('Linear system cannot be solved since matrix is singular'); 145 } 146 147 var xj = divideScalar(bj, vjj); 148 149 for (var _k = 0, _lastIndex = jIndices.length; _k < _lastIndex; _k++) { 150 var _i = jIndices[_k]; 151 bdata[_i] = [subtract(bdata[_i][0], multiplyScalar(xj, jValues[_k]))]; 152 } 153 154 x[j] = [xj]; 155 } else { 156 // degenerate row, we can choose any value 157 x[j] = [0]; 158 } 159 } 160 161 return new DenseMatrix({ 162 data: x, 163 size: [rows, 1] 164 }); 165 } 166 });