simple-squiggle

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

lsolveAll.js (6125B)


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