simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

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 });