simple-squiggle

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

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