lsolve.js (4412B)
1 import { factory } from '../../../utils/factory.js'; 2 import { createSolveValidation } from './utils/solveValidation.js'; 3 var name = 'lsolve'; 4 var dependencies = ['typed', 'matrix', 'divideScalar', 'multiplyScalar', 'subtract', 'equalScalar', 'DenseMatrix']; 5 export var createLsolve = /* #__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 forwards substitution. Matrix must be a lower triangular matrix. Throws an error if there's no solution. 20 * 21 * `L * x = b` 22 * 23 * Syntax: 24 * 25 * math.lsolve(L, b) 26 * 27 * Examples: 28 * 29 * const a = [[-2, 3], [2, 1]] 30 * const b = [11, 9] 31 * const x = lsolve(a, b) // [[-5.5], [20]] 32 * 33 * See also: 34 * 35 * lsolveAll, lup, slu, usolve, lusolve 36 * 37 * @param {Matrix, Array} L A N x N matrix or array (L) 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 _sparseForwardSubstitution(m, b); 46 }, 47 'DenseMatrix, Array | Matrix': function DenseMatrixArrayMatrix(m, b) { 48 return _denseForwardSubstitution(m, b); 49 }, 50 'Array, Array | Matrix': function ArrayArrayMatrix(a, b) { 51 var m = matrix(a); 52 53 var r = _denseForwardSubstitution(m, b); 54 55 return r.valueOf(); 56 } 57 }); 58 59 function _denseForwardSubstitution(m, b) { 60 // validate matrix and vector, return copy of column vector b 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 68 69 for (var j = 0; j < columns; j++) { 70 var bj = bdata[j][0] || 0; 71 var xj = void 0; 72 73 if (!equalScalar(bj, 0)) { 74 // non-degenerate row, find solution 75 var vjj = mdata[j][j]; 76 77 if (equalScalar(vjj, 0)) { 78 throw new Error('Linear system cannot be solved since matrix is singular'); 79 } 80 81 xj = divideScalar(bj, vjj); // loop rows 82 83 for (var i = j + 1; i < rows; i++) { 84 bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))]; 85 } 86 } else { 87 // degenerate row, we can choose any value 88 xj = 0; 89 } 90 91 x[j] = [xj]; 92 } 93 94 return new DenseMatrix({ 95 data: x, 96 size: [rows, 1] 97 }); 98 } 99 100 function _sparseForwardSubstitution(m, b) { 101 // validate matrix and vector, return copy of column vector b 102 b = solveValidation(m, b, true); 103 var bdata = b._data; 104 var rows = m._size[0]; 105 var columns = m._size[1]; 106 var values = m._values; 107 var index = m._index; 108 var ptr = m._ptr; // result 109 110 var x = []; // loop columns 111 112 for (var j = 0; j < columns; j++) { 113 var bj = bdata[j][0] || 0; 114 115 if (!equalScalar(bj, 0)) { 116 // non-degenerate row, find solution 117 var vjj = 0; // matrix values & indices (column j) 118 119 var jValues = []; 120 var jIndices = []; // first and last index in the column 121 122 var firstIndex = ptr[j]; 123 var lastIndex = ptr[j + 1]; // values in column, find value at [j, j] 124 125 for (var k = firstIndex; k < lastIndex; k++) { 126 var i = index[k]; // check row (rows are not sorted!) 127 128 if (i === j) { 129 vjj = values[k]; 130 } else if (i > j) { 131 // store lower triangular 132 jValues.push(values[k]); 133 jIndices.push(i); 134 } 135 } // at this point we must have a value in vjj 136 137 138 if (equalScalar(vjj, 0)) { 139 throw new Error('Linear system cannot be solved since matrix is singular'); 140 } 141 142 var xj = divideScalar(bj, vjj); 143 144 for (var _k = 0, l = jIndices.length; _k < l; _k++) { 145 var _i = jIndices[_k]; 146 bdata[_i] = [subtract(bdata[_i][0] || 0, multiplyScalar(xj, jValues[_k]))]; 147 } 148 149 x[j] = [xj]; 150 } else { 151 // degenerate row, we can choose any value 152 x[j] = [0]; 153 } 154 } 155 156 return new DenseMatrix({ 157 data: x, 158 size: [rows, 1] 159 }); 160 } 161 });