Spaces:
Running
Running
| // https://github.com/pair-code/umap-js Copyright 2019 Google | |
| (function webpackUniversalModuleDefinition(root, factory) { | |
| if(typeof exports === 'object' && typeof module === 'object') | |
| module.exports = factory(); | |
| else if(typeof define === 'function' && define.amd) | |
| define([], factory); | |
| else { | |
| var a = factory(); | |
| for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; | |
| } | |
| })(window, function() { | |
| return /******/ (function(modules) { // webpackBootstrap | |
| /******/ // The module cache | |
| /******/ var installedModules = {}; | |
| /******/ | |
| /******/ // The require function | |
| /******/ function __webpack_require__(moduleId) { | |
| /******/ | |
| /******/ // Check if module is in cache | |
| /******/ if(installedModules[moduleId]) { | |
| /******/ return installedModules[moduleId].exports; | |
| /******/ } | |
| /******/ // Create a new module (and put it into the cache) | |
| /******/ var module = installedModules[moduleId] = { | |
| /******/ i: moduleId, | |
| /******/ l: false, | |
| /******/ exports: {} | |
| /******/ }; | |
| /******/ | |
| /******/ // Execute the module function | |
| /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | |
| /******/ | |
| /******/ // Flag the module as loaded | |
| /******/ module.l = true; | |
| /******/ | |
| /******/ // Return the exports of the module | |
| /******/ return module.exports; | |
| /******/ } | |
| /******/ | |
| /******/ | |
| /******/ // expose the modules object (__webpack_modules__) | |
| /******/ __webpack_require__.m = modules; | |
| /******/ | |
| /******/ // expose the module cache | |
| /******/ __webpack_require__.c = installedModules; | |
| /******/ | |
| /******/ // define getter function for harmony exports | |
| /******/ __webpack_require__.d = function(exports, name, getter) { | |
| /******/ if(!__webpack_require__.o(exports, name)) { | |
| /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); | |
| /******/ } | |
| /******/ }; | |
| /******/ | |
| /******/ // define __esModule on exports | |
| /******/ __webpack_require__.r = function(exports) { | |
| /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |
| /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | |
| /******/ } | |
| /******/ Object.defineProperty(exports, '__esModule', { value: true }); | |
| /******/ }; | |
| /******/ | |
| /******/ // create a fake namespace object | |
| /******/ // mode & 1: value is a module id, require it | |
| /******/ // mode & 2: merge all properties of value into the ns | |
| /******/ // mode & 4: return value when already ns object | |
| /******/ // mode & 8|1: behave like require | |
| /******/ __webpack_require__.t = function(value, mode) { | |
| /******/ if(mode & 1) value = __webpack_require__(value); | |
| /******/ if(mode & 8) return value; | |
| /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; | |
| /******/ var ns = Object.create(null); | |
| /******/ __webpack_require__.r(ns); | |
| /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); | |
| /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); | |
| /******/ return ns; | |
| /******/ }; | |
| /******/ | |
| /******/ // getDefaultExport function for compatibility with non-harmony modules | |
| /******/ __webpack_require__.n = function(module) { | |
| /******/ var getter = module && module.__esModule ? | |
| /******/ function getDefault() { return module['default']; } : | |
| /******/ function getModuleExports() { return module; }; | |
| /******/ __webpack_require__.d(getter, 'a', getter); | |
| /******/ return getter; | |
| /******/ }; | |
| /******/ | |
| /******/ // Object.prototype.hasOwnProperty.call | |
| /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | |
| /******/ | |
| /******/ // __webpack_public_path__ | |
| /******/ __webpack_require__.p = ""; | |
| /******/ | |
| /******/ | |
| /******/ // Load entry module and return exports | |
| /******/ return __webpack_require__(__webpack_require__.s = 5); | |
| /******/ }) | |
| /************************************************************************/ | |
| /******/ ([ | |
| /* 0 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| const toString = Object.prototype.toString; | |
| function isAnyArray(object) { | |
| return toString.call(object).endsWith('Array]'); | |
| } | |
| module.exports = isAnyArray; | |
| /***/ }), | |
| /* 1 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __values = (this && this.__values) || function (o) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | |
| if (m) return m.call(o); | |
| return { | |
| next: function () { | |
| if (o && i >= o.length) o = void 0; | |
| return { value: o && o[i++], done: !o }; | |
| } | |
| }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| function tauRandInt(n, random) { | |
| return Math.floor(random() * n); | |
| } | |
| exports.tauRandInt = tauRandInt; | |
| function tauRand(random) { | |
| return random(); | |
| } | |
| exports.tauRand = tauRand; | |
| function norm(vec) { | |
| var e_1, _a; | |
| var result = 0; | |
| try { | |
| for (var vec_1 = __values(vec), vec_1_1 = vec_1.next(); !vec_1_1.done; vec_1_1 = vec_1.next()) { | |
| var item = vec_1_1.value; | |
| result += Math.pow(item, 2); | |
| } | |
| } | |
| catch (e_1_1) { e_1 = { error: e_1_1 }; } | |
| finally { | |
| try { | |
| if (vec_1_1 && !vec_1_1.done && (_a = vec_1.return)) _a.call(vec_1); | |
| } | |
| finally { if (e_1) throw e_1.error; } | |
| } | |
| return Math.sqrt(result); | |
| } | |
| exports.norm = norm; | |
| function empty(n) { | |
| var output = []; | |
| for (var i = 0; i < n; i++) { | |
| output.push(undefined); | |
| } | |
| return output; | |
| } | |
| exports.empty = empty; | |
| function range(n) { | |
| return empty(n).map(function (_, i) { return i; }); | |
| } | |
| exports.range = range; | |
| function filled(n, v) { | |
| return empty(n).map(function () { return v; }); | |
| } | |
| exports.filled = filled; | |
| function zeros(n) { | |
| return filled(n, 0); | |
| } | |
| exports.zeros = zeros; | |
| function ones(n) { | |
| return filled(n, 1); | |
| } | |
| exports.ones = ones; | |
| function linear(a, b, len) { | |
| return empty(len).map(function (_, i) { | |
| return a + i * ((b - a) / (len - 1)); | |
| }); | |
| } | |
| exports.linear = linear; | |
| function sum(input) { | |
| return input.reduce(function (sum, val) { return sum + val; }); | |
| } | |
| exports.sum = sum; | |
| function mean(input) { | |
| return sum(input) / input.length; | |
| } | |
| exports.mean = mean; | |
| function max(input) { | |
| var max = 0; | |
| for (var i = 0; i < input.length; i++) { | |
| max = input[i] > max ? input[i] : max; | |
| } | |
| return max; | |
| } | |
| exports.max = max; | |
| function max2d(input) { | |
| var max = 0; | |
| for (var i = 0; i < input.length; i++) { | |
| for (var j = 0; j < input[i].length; j++) { | |
| max = input[i][j] > max ? input[i][j] : max; | |
| } | |
| } | |
| return max; | |
| } | |
| exports.max2d = max2d; | |
| function rejectionSample(nSamples, poolSize, random) { | |
| var result = zeros(nSamples); | |
| for (var i = 0; i < nSamples; i++) { | |
| var rejectSample = true; | |
| while (rejectSample) { | |
| var j = tauRandInt(poolSize, random); | |
| var broken = false; | |
| for (var k = 0; k < i; k++) { | |
| if (j === result[k]) { | |
| broken = true; | |
| break; | |
| } | |
| } | |
| if (!broken) { | |
| rejectSample = false; | |
| } | |
| result[i] = j; | |
| } | |
| } | |
| return result; | |
| } | |
| exports.rejectionSample = rejectionSample; | |
| function reshape2d(x, a, b) { | |
| var rows = []; | |
| var count = 0; | |
| var index = 0; | |
| if (x.length !== a * b) { | |
| throw new Error('Array dimensions must match input length.'); | |
| } | |
| for (var i = 0; i < a; i++) { | |
| var col = []; | |
| for (var j = 0; j < b; j++) { | |
| col.push(x[index]); | |
| index += 1; | |
| } | |
| rows.push(col); | |
| count += 1; | |
| } | |
| return rows; | |
| } | |
| exports.reshape2d = reshape2d; | |
| /***/ }), | |
| /* 2 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | |
| result["default"] = mod; | |
| return result; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var utils = __importStar(__webpack_require__(1)); | |
| function makeHeap(nPoints, size) { | |
| var makeArrays = function (fillValue) { | |
| return utils.empty(nPoints).map(function () { | |
| return utils.filled(size, fillValue); | |
| }); | |
| }; | |
| var heap = []; | |
| heap.push(makeArrays(-1)); | |
| heap.push(makeArrays(Infinity)); | |
| heap.push(makeArrays(0)); | |
| return heap; | |
| } | |
| exports.makeHeap = makeHeap; | |
| function rejectionSample(nSamples, poolSize, random) { | |
| var result = utils.zeros(nSamples); | |
| for (var i = 0; i < nSamples; i++) { | |
| var rejectSample = true; | |
| var j = 0; | |
| while (rejectSample) { | |
| j = utils.tauRandInt(poolSize, random); | |
| var broken = false; | |
| for (var k = 0; k < i; k++) { | |
| if (j === result[k]) { | |
| broken = true; | |
| break; | |
| } | |
| } | |
| if (!broken) | |
| rejectSample = false; | |
| } | |
| result[i] = j; | |
| } | |
| return result; | |
| } | |
| exports.rejectionSample = rejectionSample; | |
| function heapPush(heap, row, weight, index, flag) { | |
| row = Math.floor(row); | |
| var indices = heap[0][row]; | |
| var weights = heap[1][row]; | |
| var isNew = heap[2][row]; | |
| if (weight >= weights[0]) { | |
| return 0; | |
| } | |
| for (var i = 0; i < indices.length; i++) { | |
| if (index === indices[i]) { | |
| return 0; | |
| } | |
| } | |
| return uncheckedHeapPush(heap, row, weight, index, flag); | |
| } | |
| exports.heapPush = heapPush; | |
| function uncheckedHeapPush(heap, row, weight, index, flag) { | |
| var indices = heap[0][row]; | |
| var weights = heap[1][row]; | |
| var isNew = heap[2][row]; | |
| if (weight >= weights[0]) { | |
| return 0; | |
| } | |
| weights[0] = weight; | |
| indices[0] = index; | |
| isNew[0] = flag; | |
| var i = 0; | |
| var iSwap = 0; | |
| while (true) { | |
| var ic1 = 2 * i + 1; | |
| var ic2 = ic1 + 1; | |
| var heapShape2 = heap[0][0].length; | |
| if (ic1 >= heapShape2) { | |
| break; | |
| } | |
| else if (ic2 >= heapShape2) { | |
| if (weights[ic1] > weight) { | |
| iSwap = ic1; | |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| else if (weights[ic1] >= weights[ic2]) { | |
| if (weight < weights[ic1]) { | |
| iSwap = ic1; | |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| else { | |
| if (weight < weights[ic2]) { | |
| iSwap = ic2; | |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| weights[i] = weights[iSwap]; | |
| indices[i] = indices[iSwap]; | |
| isNew[i] = isNew[iSwap]; | |
| i = iSwap; | |
| } | |
| weights[i] = weight; | |
| indices[i] = index; | |
| isNew[i] = flag; | |
| return 1; | |
| } | |
| exports.uncheckedHeapPush = uncheckedHeapPush; | |
| function buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random) { | |
| var candidateNeighbors = makeHeap(nVertices, maxCandidates); | |
| for (var i = 0; i < nVertices; i++) { | |
| for (var j = 0; j < nNeighbors; j++) { | |
| if (currentGraph[0][i][j] < 0) { | |
| continue; | |
| } | |
| var idx = currentGraph[0][i][j]; | |
| var isn = currentGraph[2][i][j]; | |
| var d = utils.tauRand(random); | |
| heapPush(candidateNeighbors, i, d, idx, isn); | |
| heapPush(candidateNeighbors, idx, d, i, isn); | |
| currentGraph[2][i][j] = 0; | |
| } | |
| } | |
| return candidateNeighbors; | |
| } | |
| exports.buildCandidates = buildCandidates; | |
| function deheapSort(heap) { | |
| var indices = heap[0]; | |
| var weights = heap[1]; | |
| for (var i = 0; i < indices.length; i++) { | |
| var indHeap = indices[i]; | |
| var distHeap = weights[i]; | |
| for (var j = 0; j < indHeap.length - 1; j++) { | |
| var indHeapIndex = indHeap.length - j - 1; | |
| var distHeapIndex = distHeap.length - j - 1; | |
| var temp1 = indHeap[0]; | |
| indHeap[0] = indHeap[indHeapIndex]; | |
| indHeap[indHeapIndex] = temp1; | |
| var temp2 = distHeap[0]; | |
| distHeap[0] = distHeap[distHeapIndex]; | |
| distHeap[distHeapIndex] = temp2; | |
| siftDown(distHeap, indHeap, distHeapIndex, 0); | |
| } | |
| } | |
| return { indices: indices, weights: weights }; | |
| } | |
| exports.deheapSort = deheapSort; | |
| function siftDown(heap1, heap2, ceiling, elt) { | |
| while (elt * 2 + 1 < ceiling) { | |
| var leftChild = elt * 2 + 1; | |
| var rightChild = leftChild + 1; | |
| var swap = elt; | |
| if (heap1[swap] < heap1[leftChild]) { | |
| swap = leftChild; | |
| } | |
| if (rightChild < ceiling && heap1[swap] < heap1[rightChild]) { | |
| swap = rightChild; | |
| } | |
| if (swap === elt) { | |
| break; | |
| } | |
| else { | |
| var temp1 = heap1[elt]; | |
| heap1[elt] = heap1[swap]; | |
| heap1[swap] = temp1; | |
| var temp2 = heap2[elt]; | |
| heap2[elt] = heap2[swap]; | |
| heap2[swap] = temp2; | |
| elt = swap; | |
| } | |
| } | |
| } | |
| function smallestFlagged(heap, row) { | |
| var ind = heap[0][row]; | |
| var dist = heap[1][row]; | |
| var flag = heap[2][row]; | |
| var minDist = Infinity; | |
| var resultIndex = -1; | |
| for (var i = 0; i > ind.length; i++) { | |
| if (flag[i] === 1 && dist[i] < minDist) { | |
| minDist = dist[i]; | |
| resultIndex = i; | |
| } | |
| } | |
| if (resultIndex >= 0) { | |
| flag[resultIndex] = 0; | |
| return Math.floor(ind[resultIndex]); | |
| } | |
| else { | |
| return -1; | |
| } | |
| } | |
| exports.smallestFlagged = smallestFlagged; | |
| /***/ }), | |
| /* 3 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __read = (this && this.__read) || function (o, n) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator]; | |
| if (!m) return o; | |
| var i = m.call(o), r, ar = [], e; | |
| try { | |
| while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | |
| } | |
| catch (error) { e = { error: error }; } | |
| finally { | |
| try { | |
| if (r && !r.done && (m = i["return"])) m.call(i); | |
| } | |
| finally { if (e) throw e.error; } | |
| } | |
| return ar; | |
| }; | |
| var __spread = (this && this.__spread) || function () { | |
| for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | |
| return ar; | |
| }; | |
| var __values = (this && this.__values) || function (o) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | |
| if (m) return m.call(o); | |
| return { | |
| next: function () { | |
| if (o && i >= o.length) o = void 0; | |
| return { value: o && o[i++], done: !o }; | |
| } | |
| }; | |
| }; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | |
| result["default"] = mod; | |
| return result; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var _a; | |
| var utils = __importStar(__webpack_require__(1)); | |
| var SparseMatrix = (function () { | |
| function SparseMatrix(rows, cols, values, dims) { | |
| this.entries = new Map(); | |
| this.nRows = 0; | |
| this.nCols = 0; | |
| this.rows = __spread(rows); | |
| this.cols = __spread(cols); | |
| this.values = __spread(values); | |
| for (var i = 0; i < values.length; i++) { | |
| var key = this.makeKey(this.rows[i], this.cols[i]); | |
| this.entries.set(key, i); | |
| } | |
| this.nRows = dims[0]; | |
| this.nCols = dims[1]; | |
| } | |
| SparseMatrix.prototype.makeKey = function (row, col) { | |
| return row + ":" + col; | |
| }; | |
| SparseMatrix.prototype.checkDims = function (row, col) { | |
| var withinBounds = row < this.nRows && col < this.nCols; | |
| if (!withinBounds) { | |
| throw new Error('array index out of bounds'); | |
| } | |
| }; | |
| SparseMatrix.prototype.set = function (row, col, value) { | |
| this.checkDims(row, col); | |
| var key = this.makeKey(row, col); | |
| if (!this.entries.has(key)) { | |
| this.rows.push(row); | |
| this.cols.push(col); | |
| this.values.push(value); | |
| this.entries.set(key, this.values.length - 1); | |
| } | |
| else { | |
| var index = this.entries.get(key); | |
| this.values[index] = value; | |
| } | |
| }; | |
| SparseMatrix.prototype.get = function (row, col, defaultValue) { | |
| if (defaultValue === void 0) { defaultValue = 0; } | |
| this.checkDims(row, col); | |
| var key = this.makeKey(row, col); | |
| if (this.entries.has(key)) { | |
| var index = this.entries.get(key); | |
| return this.values[index]; | |
| } | |
| else { | |
| return defaultValue; | |
| } | |
| }; | |
| SparseMatrix.prototype.getDims = function () { | |
| return [this.nRows, this.nCols]; | |
| }; | |
| SparseMatrix.prototype.getRows = function () { | |
| return __spread(this.rows); | |
| }; | |
| SparseMatrix.prototype.getCols = function () { | |
| return __spread(this.cols); | |
| }; | |
| SparseMatrix.prototype.getValues = function () { | |
| return __spread(this.values); | |
| }; | |
| SparseMatrix.prototype.forEach = function (fn) { | |
| for (var i = 0; i < this.values.length; i++) { | |
| fn(this.values[i], this.rows[i], this.cols[i]); | |
| } | |
| }; | |
| SparseMatrix.prototype.map = function (fn) { | |
| var vals = []; | |
| for (var i = 0; i < this.values.length; i++) { | |
| vals.push(fn(this.values[i], this.rows[i], this.cols[i])); | |
| } | |
| var dims = [this.nRows, this.nCols]; | |
| return new SparseMatrix(this.rows, this.cols, vals, dims); | |
| }; | |
| SparseMatrix.prototype.toArray = function () { | |
| var _this = this; | |
| var rows = utils.empty(this.nRows); | |
| var output = rows.map(function () { | |
| return utils.zeros(_this.nCols); | |
| }); | |
| for (var i = 0; i < this.values.length; i++) { | |
| output[this.rows[i]][this.cols[i]] = this.values[i]; | |
| } | |
| return output; | |
| }; | |
| return SparseMatrix; | |
| }()); | |
| exports.SparseMatrix = SparseMatrix; | |
| function transpose(matrix) { | |
| var cols = []; | |
| var rows = []; | |
| var vals = []; | |
| matrix.forEach(function (value, row, col) { | |
| cols.push(row); | |
| rows.push(col); | |
| vals.push(value); | |
| }); | |
| var dims = [matrix.nCols, matrix.nRows]; | |
| return new SparseMatrix(rows, cols, vals, dims); | |
| } | |
| exports.transpose = transpose; | |
| function identity(size) { | |
| var _a = __read(size, 1), rows = _a[0]; | |
| var matrix = new SparseMatrix([], [], [], size); | |
| for (var i = 0; i < rows; i++) { | |
| matrix.set(i, i, 1); | |
| } | |
| return matrix; | |
| } | |
| exports.identity = identity; | |
| function pairwiseMultiply(a, b) { | |
| return elementWise(a, b, function (x, y) { return x * y; }); | |
| } | |
| exports.pairwiseMultiply = pairwiseMultiply; | |
| function add(a, b) { | |
| return elementWise(a, b, function (x, y) { return x + y; }); | |
| } | |
| exports.add = add; | |
| function subtract(a, b) { | |
| return elementWise(a, b, function (x, y) { return x - y; }); | |
| } | |
| exports.subtract = subtract; | |
| function maximum(a, b) { | |
| return elementWise(a, b, function (x, y) { return (x > y ? x : y); }); | |
| } | |
| exports.maximum = maximum; | |
| function multiplyScalar(a, scalar) { | |
| return a.map(function (value) { | |
| return value * scalar; | |
| }); | |
| } | |
| exports.multiplyScalar = multiplyScalar; | |
| function eliminateZeros(m) { | |
| var zeroIndices = new Set(); | |
| var values = m.getValues(); | |
| var rows = m.getRows(); | |
| var cols = m.getCols(); | |
| for (var i = 0; i < values.length; i++) { | |
| if (values[i] === 0) { | |
| zeroIndices.add(i); | |
| } | |
| } | |
| var removeByZeroIndex = function (_, index) { return !zeroIndices.has(index); }; | |
| var nextValues = values.filter(removeByZeroIndex); | |
| var nextRows = rows.filter(removeByZeroIndex); | |
| var nextCols = cols.filter(removeByZeroIndex); | |
| return new SparseMatrix(nextRows, nextCols, nextValues, m.getDims()); | |
| } | |
| exports.eliminateZeros = eliminateZeros; | |
| function normalize(m, normType) { | |
| if (normType === void 0) { normType = "l2"; } | |
| var e_1, _a; | |
| var normFn = normFns[normType]; | |
| var colsByRow = new Map(); | |
| m.forEach(function (_, row, col) { | |
| var cols = colsByRow.get(row) || []; | |
| cols.push(col); | |
| colsByRow.set(row, cols); | |
| }); | |
| var nextMatrix = new SparseMatrix([], [], [], m.getDims()); | |
| var _loop_1 = function (row) { | |
| var cols = colsByRow.get(row).sort(); | |
| var vals = cols.map(function (col) { return m.get(row, col); }); | |
| var norm = normFn(vals); | |
| for (var i = 0; i < norm.length; i++) { | |
| nextMatrix.set(row, cols[i], norm[i]); | |
| } | |
| }; | |
| try { | |
| for (var _b = __values(colsByRow.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { | |
| var row = _c.value; | |
| _loop_1(row); | |
| } | |
| } | |
| catch (e_1_1) { e_1 = { error: e_1_1 }; } | |
| finally { | |
| try { | |
| if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | |
| } | |
| finally { if (e_1) throw e_1.error; } | |
| } | |
| return nextMatrix; | |
| } | |
| exports.normalize = normalize; | |
| var normFns = (_a = {}, | |
| _a["max"] = function (xs) { | |
| var max = -Infinity; | |
| for (var i = 0; i < xs.length; i++) { | |
| max = xs[i] > max ? xs[i] : max; | |
| } | |
| return xs.map(function (x) { return x / max; }); | |
| }, | |
| _a["l1"] = function (xs) { | |
| var sum = 0; | |
| for (var i = 0; i < xs.length; i++) { | |
| sum += xs[i]; | |
| } | |
| return xs.map(function (x) { return x / sum; }); | |
| }, | |
| _a["l2"] = function (xs) { | |
| var sum = 0; | |
| for (var i = 0; i < xs.length; i++) { | |
| sum += Math.pow(xs[i], 2); | |
| } | |
| return xs.map(function (x) { return Math.sqrt(Math.pow(x, 2) / sum); }); | |
| }, | |
| _a); | |
| function elementWise(a, b, op) { | |
| var visited = new Set(); | |
| var rows = []; | |
| var cols = []; | |
| var vals = []; | |
| var operate = function (row, col) { | |
| rows.push(row); | |
| cols.push(col); | |
| var nextValue = op(a.get(row, col), b.get(row, col)); | |
| vals.push(nextValue); | |
| }; | |
| var valuesA = a.getValues(); | |
| var rowsA = a.getRows(); | |
| var colsA = a.getCols(); | |
| for (var i = 0; i < valuesA.length; i++) { | |
| var row = rowsA[i]; | |
| var col = colsA[i]; | |
| var key = row + ":" + col; | |
| visited.add(key); | |
| operate(row, col); | |
| } | |
| var valuesB = b.getValues(); | |
| var rowsB = b.getRows(); | |
| var colsB = b.getCols(); | |
| for (var i = 0; i < valuesB.length; i++) { | |
| var row = rowsB[i]; | |
| var col = colsB[i]; | |
| var key = row + ":" + col; | |
| if (visited.has(key)) | |
| continue; | |
| operate(row, col); | |
| } | |
| var dims = [a.nRows, a.nCols]; | |
| return new SparseMatrix(rows, cols, vals, dims); | |
| } | |
| function getCSR(x) { | |
| var entries = []; | |
| x.forEach(function (value, row, col) { | |
| entries.push({ value: value, row: row, col: col }); | |
| }); | |
| entries.sort(function (a, b) { | |
| if (a.row === b.row) { | |
| return a.col - b.col; | |
| } | |
| else { | |
| return a.row - b.col; | |
| } | |
| }); | |
| var indices = []; | |
| var values = []; | |
| var indptr = []; | |
| var currentRow = -1; | |
| for (var i = 0; i < entries.length; i++) { | |
| var _a = entries[i], row = _a.row, col = _a.col, value = _a.value; | |
| if (row !== currentRow) { | |
| currentRow = row; | |
| indptr.push(i); | |
| } | |
| indices.push(col); | |
| values.push(value); | |
| } | |
| return { indices: indices, values: values, indptr: indptr }; | |
| } | |
| exports.getCSR = getCSR; | |
| /***/ }), | |
| /* 4 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __read = (this && this.__read) || function (o, n) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator]; | |
| if (!m) return o; | |
| var i = m.call(o), r, ar = [], e; | |
| try { | |
| while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | |
| } | |
| catch (error) { e = { error: error }; } | |
| finally { | |
| try { | |
| if (r && !r.done && (m = i["return"])) m.call(i); | |
| } | |
| finally { if (e) throw e.error; } | |
| } | |
| return ar; | |
| }; | |
| var __spread = (this && this.__spread) || function () { | |
| for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | |
| return ar; | |
| }; | |
| var __values = (this && this.__values) || function (o) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | |
| if (m) return m.call(o); | |
| return { | |
| next: function () { | |
| if (o && i >= o.length) o = void 0; | |
| return { value: o && o[i++], done: !o }; | |
| } | |
| }; | |
| }; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | |
| result["default"] = mod; | |
| return result; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var utils = __importStar(__webpack_require__(1)); | |
| var FlatTree = (function () { | |
| function FlatTree(hyperplanes, offsets, children, indices) { | |
| this.hyperplanes = hyperplanes; | |
| this.offsets = offsets; | |
| this.children = children; | |
| this.indices = indices; | |
| } | |
| return FlatTree; | |
| }()); | |
| exports.FlatTree = FlatTree; | |
| function makeForest(data, nNeighbors, nTrees, random) { | |
| var leafSize = Math.max(10, nNeighbors); | |
| var trees = utils | |
| .range(nTrees) | |
| .map(function (_, i) { return makeTree(data, leafSize, i, random); }); | |
| var forest = trees.map(function (tree) { return flattenTree(tree, leafSize); }); | |
| return forest; | |
| } | |
| exports.makeForest = makeForest; | |
| function makeTree(data, leafSize, n, random) { | |
| if (leafSize === void 0) { leafSize = 30; } | |
| var indices = utils.range(data.length); | |
| var tree = makeEuclideanTree(data, indices, leafSize, n, random); | |
| return tree; | |
| } | |
| function makeEuclideanTree(data, indices, leafSize, q, random) { | |
| if (leafSize === void 0) { leafSize = 30; } | |
| if (indices.length > leafSize) { | |
| var splitResults = euclideanRandomProjectionSplit(data, indices, random); | |
| var indicesLeft = splitResults.indicesLeft, indicesRight = splitResults.indicesRight, hyperplane = splitResults.hyperplane, offset = splitResults.offset; | |
| var leftChild = makeEuclideanTree(data, indicesLeft, leafSize, q + 1, random); | |
| var rightChild = makeEuclideanTree(data, indicesRight, leafSize, q + 1, random); | |
| var node = { leftChild: leftChild, rightChild: rightChild, isLeaf: false, hyperplane: hyperplane, offset: offset }; | |
| return node; | |
| } | |
| else { | |
| var node = { indices: indices, isLeaf: true }; | |
| return node; | |
| } | |
| } | |
| function euclideanRandomProjectionSplit(data, indices, random) { | |
| var dim = data[0].length; | |
| var leftIndex = utils.tauRandInt(indices.length, random); | |
| var rightIndex = utils.tauRandInt(indices.length, random); | |
| rightIndex += leftIndex === rightIndex ? 1 : 0; | |
| rightIndex = rightIndex % indices.length; | |
| var left = indices[leftIndex]; | |
| var right = indices[rightIndex]; | |
| var hyperplaneOffset = 0; | |
| var hyperplaneVector = utils.zeros(dim); | |
| for (var i = 0; i < hyperplaneVector.length; i++) { | |
| hyperplaneVector[i] = data[left][i] - data[right][i]; | |
| hyperplaneOffset -= | |
| (hyperplaneVector[i] * (data[left][i] + data[right][i])) / 2.0; | |
| } | |
| var nLeft = 0; | |
| var nRight = 0; | |
| var side = utils.zeros(indices.length); | |
| for (var i = 0; i < indices.length; i++) { | |
| var margin = hyperplaneOffset; | |
| for (var d = 0; d < dim; d++) { | |
| margin += hyperplaneVector[d] * data[indices[i]][d]; | |
| } | |
| if (margin === 0) { | |
| side[i] = utils.tauRandInt(2, random); | |
| if (side[i] === 0) { | |
| nLeft += 1; | |
| } | |
| else { | |
| nRight += 1; | |
| } | |
| } | |
| else if (margin > 0) { | |
| side[i] = 0; | |
| nLeft += 1; | |
| } | |
| else { | |
| side[i] = 1; | |
| nRight += 1; | |
| } | |
| } | |
| var indicesLeft = utils.zeros(nLeft); | |
| var indicesRight = utils.zeros(nRight); | |
| nLeft = 0; | |
| nRight = 0; | |
| for (var i in utils.range(side.length)) { | |
| if (side[i] === 0) { | |
| indicesLeft[nLeft] = indices[i]; | |
| nLeft += 1; | |
| } | |
| else { | |
| indicesRight[nRight] = indices[i]; | |
| nRight += 1; | |
| } | |
| } | |
| return { | |
| indicesLeft: indicesLeft, | |
| indicesRight: indicesRight, | |
| hyperplane: hyperplaneVector, | |
| offset: hyperplaneOffset, | |
| }; | |
| } | |
| function flattenTree(tree, leafSize) { | |
| var nNodes = numNodes(tree); | |
| var nLeaves = numLeaves(tree); | |
| var hyperplanes = utils | |
| .range(nNodes) | |
| .map(function () { return utils.zeros(tree.hyperplane.length); }); | |
| var offsets = utils.zeros(nNodes); | |
| var children = utils.range(nNodes).map(function () { return [-1, -1]; }); | |
| var indices = utils | |
| .range(nLeaves) | |
| .map(function () { return utils.range(leafSize).map(function () { return -1; }); }); | |
| recursiveFlatten(tree, hyperplanes, offsets, children, indices, 0, 0); | |
| return new FlatTree(hyperplanes, offsets, children, indices); | |
| } | |
| function recursiveFlatten(tree, hyperplanes, offsets, children, indices, nodeNum, leafNum) { | |
| var _a; | |
| if (tree.isLeaf) { | |
| children[nodeNum][0] = -leafNum; | |
| (_a = indices[leafNum]).splice.apply(_a, __spread([0, tree.indices.length], tree.indices)); | |
| leafNum += 1; | |
| return { nodeNum: nodeNum, leafNum: leafNum }; | |
| } | |
| else { | |
| hyperplanes[nodeNum] = tree.hyperplane; | |
| offsets[nodeNum] = tree.offset; | |
| children[nodeNum][0] = nodeNum + 1; | |
| var oldNodeNum = nodeNum; | |
| var res = recursiveFlatten(tree.leftChild, hyperplanes, offsets, children, indices, nodeNum + 1, leafNum); | |
| nodeNum = res.nodeNum; | |
| leafNum = res.leafNum; | |
| children[oldNodeNum][1] = nodeNum + 1; | |
| res = recursiveFlatten(tree.rightChild, hyperplanes, offsets, children, indices, nodeNum + 1, leafNum); | |
| return { nodeNum: res.nodeNum, leafNum: res.leafNum }; | |
| } | |
| } | |
| function numNodes(tree) { | |
| if (tree.isLeaf) { | |
| return 1; | |
| } | |
| else { | |
| return 1 + numNodes(tree.leftChild) + numNodes(tree.rightChild); | |
| } | |
| } | |
| function numLeaves(tree) { | |
| if (tree.isLeaf) { | |
| return 1; | |
| } | |
| else { | |
| return numLeaves(tree.leftChild) + numLeaves(tree.rightChild); | |
| } | |
| } | |
| function makeLeafArray(rpForest) { | |
| var e_1, _a; | |
| if (rpForest.length > 0) { | |
| var output = []; | |
| try { | |
| for (var rpForest_1 = __values(rpForest), rpForest_1_1 = rpForest_1.next(); !rpForest_1_1.done; rpForest_1_1 = rpForest_1.next()) { | |
| var tree = rpForest_1_1.value; | |
| output.push.apply(output, __spread(tree.indices)); | |
| } | |
| } | |
| catch (e_1_1) { e_1 = { error: e_1_1 }; } | |
| finally { | |
| try { | |
| if (rpForest_1_1 && !rpForest_1_1.done && (_a = rpForest_1.return)) _a.call(rpForest_1); | |
| } | |
| finally { if (e_1) throw e_1.error; } | |
| } | |
| return output; | |
| } | |
| else { | |
| return [[-1]]; | |
| } | |
| } | |
| exports.makeLeafArray = makeLeafArray; | |
| function selectSide(hyperplane, offset, point, random) { | |
| var margin = offset; | |
| for (var d = 0; d < point.length; d++) { | |
| margin += hyperplane[d] * point[d]; | |
| } | |
| if (margin === 0) { | |
| var side = utils.tauRandInt(2, random); | |
| return side; | |
| } | |
| else if (margin > 0) { | |
| return 0; | |
| } | |
| else { | |
| return 1; | |
| } | |
| } | |
| function searchFlatTree(point, tree, random) { | |
| var node = 0; | |
| while (tree.children[node][0] > 0) { | |
| var side = selectSide(tree.hyperplanes[node], tree.offsets[node], point, random); | |
| if (side === 0) { | |
| node = tree.children[node][0]; | |
| } | |
| else { | |
| node = tree.children[node][1]; | |
| } | |
| } | |
| var index = -1 * tree.children[node][0]; | |
| return tree.indices[index]; | |
| } | |
| exports.searchFlatTree = searchFlatTree; | |
| /***/ }), | |
| /* 5 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var umap_1 = __webpack_require__(6); | |
| exports.UMAP = umap_1.UMAP; | |
| /***/ }), | |
| /* 6 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | |
| return new (P || (P = Promise))(function (resolve, reject) { | |
| function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | |
| function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | |
| function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | |
| step((generator = generator.apply(thisArg, _arguments || [])).next()); | |
| }); | |
| }; | |
| var __generator = (this && this.__generator) || function (thisArg, body) { | |
| var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | |
| return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | |
| function verb(n) { return function (v) { return step([n, v]); }; } | |
| function step(op) { | |
| if (f) throw new TypeError("Generator is already executing."); | |
| while (_) try { | |
| if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | |
| if (y = 0, t) op = [op[0] & 2, t.value]; | |
| switch (op[0]) { | |
| case 0: case 1: t = op; break; | |
| case 4: _.label++; return { value: op[1], done: false }; | |
| case 5: _.label++; y = op[1]; op = [0]; continue; | |
| case 7: op = _.ops.pop(); _.trys.pop(); continue; | |
| default: | |
| if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | |
| if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | |
| if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | |
| if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | |
| if (t[2]) _.ops.pop(); | |
| _.trys.pop(); continue; | |
| } | |
| op = body.call(thisArg, _); | |
| } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | |
| if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | |
| } | |
| }; | |
| var __read = (this && this.__read) || function (o, n) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator]; | |
| if (!m) return o; | |
| var i = m.call(o), r, ar = [], e; | |
| try { | |
| while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | |
| } | |
| catch (error) { e = { error: error }; } | |
| finally { | |
| try { | |
| if (r && !r.done && (m = i["return"])) m.call(i); | |
| } | |
| finally { if (e) throw e.error; } | |
| } | |
| return ar; | |
| }; | |
| var __spread = (this && this.__spread) || function () { | |
| for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | |
| return ar; | |
| }; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | |
| result["default"] = mod; | |
| return result; | |
| }; | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var heap = __importStar(__webpack_require__(2)); | |
| var matrix = __importStar(__webpack_require__(3)); | |
| var nnDescent = __importStar(__webpack_require__(7)); | |
| var tree = __importStar(__webpack_require__(4)); | |
| var utils = __importStar(__webpack_require__(1)); | |
| var ml_levenberg_marquardt_1 = __importDefault(__webpack_require__(8)); | |
| var SMOOTH_K_TOLERANCE = 1e-5; | |
| var MIN_K_DIST_SCALE = 1e-3; | |
| var UMAP = (function () { | |
| function UMAP(params) { | |
| if (params === void 0) { params = {}; } | |
| var _this = this; | |
| this.learningRate = 1.0; | |
| this.localConnectivity = 1.0; | |
| this.minDist = 0.1; | |
| this.nComponents = 2; | |
| this.nEpochs = 0; | |
| this.nNeighbors = 15; | |
| this.negativeSampleRate = 5; | |
| this.random = Math.random; | |
| this.repulsionStrength = 1.0; | |
| this.setOpMixRatio = 1.0; | |
| this.spread = 1.0; | |
| this.transformQueueSize = 4.0; | |
| this.targetMetric = "categorical"; | |
| this.targetWeight = 0.5; | |
| this.targetNNeighbors = this.nNeighbors; | |
| this.distanceFn = euclidean; | |
| this.isInitialized = false; | |
| this.rpForest = []; | |
| this.embedding = []; | |
| this.optimizationState = new OptimizationState(); | |
| var setParam = function (key) { | |
| if (params[key] !== undefined) | |
| _this[key] = params[key]; | |
| }; | |
| setParam('distanceFn'); | |
| setParam('learningRate'); | |
| setParam('localConnectivity'); | |
| setParam('minDist'); | |
| setParam('nComponents'); | |
| setParam('nEpochs'); | |
| setParam('nNeighbors'); | |
| setParam('negativeSampleRate'); | |
| setParam('random'); | |
| setParam('repulsionStrength'); | |
| setParam('setOpMixRatio'); | |
| setParam('spread'); | |
| setParam('transformQueueSize'); | |
| } | |
| UMAP.prototype.fit = function (X) { | |
| this.initializeFit(X); | |
| this.optimizeLayout(); | |
| return this.embedding; | |
| }; | |
| UMAP.prototype.fitAsync = function (X, callback) { | |
| if (callback === void 0) { callback = function () { return true; }; } | |
| return __awaiter(this, void 0, void 0, function () { | |
| return __generator(this, function (_a) { | |
| switch (_a.label) { | |
| case 0: | |
| this.initializeFit(X); | |
| return [4, this.optimizeLayoutAsync(callback)]; | |
| case 1: | |
| _a.sent(); | |
| return [2, this.embedding]; | |
| } | |
| }); | |
| }); | |
| }; | |
| UMAP.prototype.setSupervisedProjection = function (Y, params) { | |
| if (params === void 0) { params = {}; } | |
| this.Y = Y; | |
| this.targetMetric = params.targetMetric || this.targetMetric; | |
| this.targetWeight = params.targetWeight || this.targetWeight; | |
| this.targetNNeighbors = params.targetNNeighbors || this.targetNNeighbors; | |
| }; | |
| UMAP.prototype.setPrecomputedKNN = function (knnIndices, knnDistances) { | |
| this.knnIndices = knnIndices; | |
| this.knnDistances = knnDistances; | |
| }; | |
| UMAP.prototype.initializeFit = function (X) { | |
| if (this.X === X && this.isInitialized) { | |
| return this.getNEpochs(); | |
| } | |
| this.X = X; | |
| if (!this.knnIndices && !this.knnDistances) { | |
| var knnResults = this.nearestNeighbors(X); | |
| this.knnIndices = knnResults.knnIndices; | |
| this.knnDistances = knnResults.knnDistances; | |
| } | |
| this.graph = this.fuzzySimplicialSet(X, this.nNeighbors, this.setOpMixRatio); | |
| this.makeSearchFns(); | |
| this.searchGraph = this.makeSearchGraph(X); | |
| this.processGraphForSupervisedProjection(); | |
| var _a = this.initializeSimplicialSetEmbedding(), head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample; | |
| this.optimizationState.head = head; | |
| this.optimizationState.tail = tail; | |
| this.optimizationState.epochsPerSample = epochsPerSample; | |
| this.initializeOptimization(); | |
| this.prepareForOptimizationLoop(); | |
| this.isInitialized = true; | |
| return this.getNEpochs(); | |
| }; | |
| UMAP.prototype.makeSearchFns = function () { | |
| var _a = nnDescent.makeInitializations(this.distanceFn), initFromTree = _a.initFromTree, initFromRandom = _a.initFromRandom; | |
| this.initFromTree = initFromTree; | |
| this.initFromRandom = initFromRandom; | |
| this.search = nnDescent.makeInitializedNNSearch(this.distanceFn); | |
| }; | |
| UMAP.prototype.makeSearchGraph = function (X) { | |
| var knnIndices = this.knnIndices; | |
| var knnDistances = this.knnDistances; | |
| var dims = [X.length, X.length]; | |
| var searchGraph = new matrix.SparseMatrix([], [], [], dims); | |
| for (var i = 0; i < knnIndices.length; i++) { | |
| var knn = knnIndices[i]; | |
| var distances = knnDistances[i]; | |
| for (var j = 0; j < knn.length; j++) { | |
| var neighbor = knn[j]; | |
| var distance = distances[j]; | |
| if (distance > 0) { | |
| searchGraph.set(i, neighbor, distance); | |
| } | |
| } | |
| } | |
| var transpose = matrix.transpose(searchGraph); | |
| return matrix.maximum(searchGraph, transpose); | |
| }; | |
| UMAP.prototype.transform = function (toTransform) { | |
| var _this = this; | |
| var rawData = this.X; | |
| if (rawData === undefined || rawData.length === 0) { | |
| throw new Error('No data has been fit.'); | |
| } | |
| var nNeighbors = Math.floor(this.nNeighbors * this.transformQueueSize); | |
| var init = nnDescent.initializeSearch(this.rpForest, rawData, toTransform, nNeighbors, this.initFromRandom, this.initFromTree, this.random); | |
| var result = this.search(rawData, this.searchGraph, init, toTransform); | |
| var _a = heap.deheapSort(result), indices = _a.indices, distances = _a.weights; | |
| indices = indices.map(function (x) { return x.slice(0, _this.nNeighbors); }); | |
| distances = distances.map(function (x) { return x.slice(0, _this.nNeighbors); }); | |
| var adjustedLocalConnectivity = Math.max(0, this.localConnectivity - 1); | |
| var _b = this.smoothKNNDistance(distances, this.nNeighbors, adjustedLocalConnectivity), sigmas = _b.sigmas, rhos = _b.rhos; | |
| var _c = this.computeMembershipStrengths(indices, distances, sigmas, rhos), rows = _c.rows, cols = _c.cols, vals = _c.vals; | |
| var size = [toTransform.length, rawData.length]; | |
| var graph = new matrix.SparseMatrix(rows, cols, vals, size); | |
| var normed = matrix.normalize(graph, "l1"); | |
| var csrMatrix = matrix.getCSR(normed); | |
| var nPoints = toTransform.length; | |
| var eIndices = utils.reshape2d(csrMatrix.indices, nPoints, this.nNeighbors); | |
| var eWeights = utils.reshape2d(csrMatrix.values, nPoints, this.nNeighbors); | |
| var embedding = initTransform(eIndices, eWeights, this.embedding); | |
| var nEpochs = this.nEpochs | |
| ? this.nEpochs / 3 | |
| : graph.nRows <= 10000 | |
| ? 100 | |
| : 30; | |
| var graphMax = graph | |
| .getValues() | |
| .reduce(function (max, val) { return (val > max ? val : max); }, 0); | |
| graph = graph.map(function (value) { return (value < graphMax / nEpochs ? 0 : value); }); | |
| graph = matrix.eliminateZeros(graph); | |
| var epochsPerSample = this.makeEpochsPerSample(graph.getValues(), nEpochs); | |
| var head = graph.getRows(); | |
| var tail = graph.getCols(); | |
| this.assignOptimizationStateParameters({ | |
| headEmbedding: embedding, | |
| tailEmbedding: this.embedding, | |
| head: head, | |
| tail: tail, | |
| currentEpoch: 0, | |
| nEpochs: nEpochs, | |
| nVertices: graph.getDims()[1], | |
| epochsPerSample: epochsPerSample, | |
| }); | |
| this.prepareForOptimizationLoop(); | |
| return this.optimizeLayout(); | |
| }; | |
| UMAP.prototype.processGraphForSupervisedProjection = function () { | |
| var _a = this, Y = _a.Y, X = _a.X; | |
| if (Y) { | |
| if (Y.length !== X.length) { | |
| throw new Error('Length of X and y must be equal'); | |
| } | |
| if (this.targetMetric === "categorical") { | |
| var lt = this.targetWeight < 1.0; | |
| var farDist = lt ? 2.5 * (1.0 / (1.0 - this.targetWeight)) : 1.0e12; | |
| this.graph = this.categoricalSimplicialSetIntersection(this.graph, Y, farDist); | |
| } | |
| } | |
| }; | |
| UMAP.prototype.step = function () { | |
| var currentEpoch = this.optimizationState.currentEpoch; | |
| if (currentEpoch < this.getNEpochs()) { | |
| this.optimizeLayoutStep(currentEpoch); | |
| } | |
| return this.optimizationState.currentEpoch; | |
| }; | |
| UMAP.prototype.getEmbedding = function () { | |
| return this.embedding; | |
| }; | |
| UMAP.prototype.nearestNeighbors = function (X) { | |
| var _a = this, distanceFn = _a.distanceFn, nNeighbors = _a.nNeighbors; | |
| var log2 = function (n) { return Math.log(n) / Math.log(2); }; | |
| var metricNNDescent = nnDescent.makeNNDescent(distanceFn, this.random); | |
| var round = function (n) { | |
| return n === 0.5 ? 0 : Math.round(n); | |
| }; | |
| var nTrees = 5 + Math.floor(round(Math.pow(X.length, 0.5) / 20.0)); | |
| var nIters = Math.max(5, Math.floor(Math.round(log2(X.length)))); | |
| this.rpForest = tree.makeForest(X, nNeighbors, nTrees, this.random); | |
| var leafArray = tree.makeLeafArray(this.rpForest); | |
| var _b = metricNNDescent(X, leafArray, nNeighbors, nIters), indices = _b.indices, weights = _b.weights; | |
| return { knnIndices: indices, knnDistances: weights }; | |
| }; | |
| UMAP.prototype.fuzzySimplicialSet = function (X, nNeighbors, setOpMixRatio) { | |
| if (setOpMixRatio === void 0) { setOpMixRatio = 1.0; } | |
| var _a = this, _b = _a.knnIndices, knnIndices = _b === void 0 ? [] : _b, _c = _a.knnDistances, knnDistances = _c === void 0 ? [] : _c, localConnectivity = _a.localConnectivity; | |
| var _d = this.smoothKNNDistance(knnDistances, nNeighbors, localConnectivity), sigmas = _d.sigmas, rhos = _d.rhos; | |
| var _e = this.computeMembershipStrengths(knnIndices, knnDistances, sigmas, rhos), rows = _e.rows, cols = _e.cols, vals = _e.vals; | |
| var size = [X.length, X.length]; | |
| var sparseMatrix = new matrix.SparseMatrix(rows, cols, vals, size); | |
| var transpose = matrix.transpose(sparseMatrix); | |
| var prodMatrix = matrix.pairwiseMultiply(sparseMatrix, transpose); | |
| var a = matrix.subtract(matrix.add(sparseMatrix, transpose), prodMatrix); | |
| var b = matrix.multiplyScalar(a, setOpMixRatio); | |
| var c = matrix.multiplyScalar(prodMatrix, 1.0 - setOpMixRatio); | |
| var result = matrix.add(b, c); | |
| return result; | |
| }; | |
| UMAP.prototype.categoricalSimplicialSetIntersection = function (simplicialSet, target, farDist, unknownDist) { | |
| if (unknownDist === void 0) { unknownDist = 1.0; } | |
| var intersection = fastIntersection(simplicialSet, target, unknownDist, farDist); | |
| intersection = matrix.eliminateZeros(intersection); | |
| return resetLocalConnectivity(intersection); | |
| }; | |
| UMAP.prototype.smoothKNNDistance = function (distances, k, localConnectivity, nIter, bandwidth) { | |
| if (localConnectivity === void 0) { localConnectivity = 1.0; } | |
| if (nIter === void 0) { nIter = 64; } | |
| if (bandwidth === void 0) { bandwidth = 1.0; } | |
| var target = (Math.log(k) / Math.log(2)) * bandwidth; | |
| var rho = utils.zeros(distances.length); | |
| var result = utils.zeros(distances.length); | |
| for (var i = 0; i < distances.length; i++) { | |
| var lo = 0.0; | |
| var hi = Infinity; | |
| var mid = 1.0; | |
| var ithDistances = distances[i]; | |
| var nonZeroDists = ithDistances.filter(function (d) { return d > 0.0; }); | |
| if (nonZeroDists.length >= localConnectivity) { | |
| var index = Math.floor(localConnectivity); | |
| var interpolation = localConnectivity - index; | |
| if (index > 0) { | |
| rho[i] = nonZeroDists[index - 1]; | |
| if (interpolation > SMOOTH_K_TOLERANCE) { | |
| rho[i] += | |
| interpolation * (nonZeroDists[index] - nonZeroDists[index - 1]); | |
| } | |
| } | |
| else { | |
| rho[i] = interpolation * nonZeroDists[0]; | |
| } | |
| } | |
| else if (nonZeroDists.length > 0) { | |
| rho[i] = utils.max(nonZeroDists); | |
| } | |
| for (var n = 0; n < nIter; n++) { | |
| var psum = 0.0; | |
| for (var j = 1; j < distances[i].length; j++) { | |
| var d = distances[i][j] - rho[i]; | |
| if (d > 0) { | |
| psum += Math.exp(-(d / mid)); | |
| } | |
| else { | |
| psum += 1.0; | |
| } | |
| } | |
| if (Math.abs(psum - target) < SMOOTH_K_TOLERANCE) { | |
| break; | |
| } | |
| if (psum > target) { | |
| hi = mid; | |
| mid = (lo + hi) / 2.0; | |
| } | |
| else { | |
| lo = mid; | |
| if (hi === Infinity) { | |
| mid *= 2; | |
| } | |
| else { | |
| mid = (lo + hi) / 2.0; | |
| } | |
| } | |
| } | |
| result[i] = mid; | |
| if (rho[i] > 0.0) { | |
| var meanIthDistances = utils.mean(ithDistances); | |
| if (result[i] < MIN_K_DIST_SCALE * meanIthDistances) { | |
| result[i] = MIN_K_DIST_SCALE * meanIthDistances; | |
| } | |
| } | |
| else { | |
| var meanDistances = utils.mean(distances.map(utils.mean)); | |
| if (result[i] < MIN_K_DIST_SCALE * meanDistances) { | |
| result[i] = MIN_K_DIST_SCALE * meanDistances; | |
| } | |
| } | |
| } | |
| return { sigmas: result, rhos: rho }; | |
| }; | |
| UMAP.prototype.computeMembershipStrengths = function (knnIndices, knnDistances, sigmas, rhos) { | |
| var nSamples = knnIndices.length; | |
| var nNeighbors = knnIndices[0].length; | |
| var rows = utils.zeros(nSamples * nNeighbors); | |
| var cols = utils.zeros(nSamples * nNeighbors); | |
| var vals = utils.zeros(nSamples * nNeighbors); | |
| for (var i = 0; i < nSamples; i++) { | |
| for (var j = 0; j < nNeighbors; j++) { | |
| var val = 0; | |
| if (knnIndices[i][j] === -1) { | |
| continue; | |
| } | |
| if (knnIndices[i][j] === i) { | |
| val = 0.0; | |
| } | |
| else if (knnDistances[i][j] - rhos[i] <= 0.0) { | |
| val = 1.0; | |
| } | |
| else { | |
| val = Math.exp(-((knnDistances[i][j] - rhos[i]) / sigmas[i])); | |
| } | |
| rows[i * nNeighbors + j] = i; | |
| cols[i * nNeighbors + j] = knnIndices[i][j]; | |
| vals[i * nNeighbors + j] = val; | |
| } | |
| } | |
| return { rows: rows, cols: cols, vals: vals }; | |
| }; | |
| UMAP.prototype.initializeSimplicialSetEmbedding = function () { | |
| var _this = this; | |
| var nEpochs = this.getNEpochs(); | |
| var nComponents = this.nComponents; | |
| var graphValues = this.graph.getValues(); | |
| var graphMax = 0; | |
| for (var i = 0; i < graphValues.length; i++) { | |
| var value = graphValues[i]; | |
| if (graphMax < graphValues[i]) { | |
| graphMax = value; | |
| } | |
| } | |
| var graph = this.graph.map(function (value) { | |
| if (value < graphMax / nEpochs) { | |
| return 0; | |
| } | |
| else { | |
| return value; | |
| } | |
| }); | |
| this.embedding = utils.zeros(graph.nRows).map(function () { | |
| return utils.zeros(nComponents).map(function () { | |
| return utils.tauRand(_this.random) * 20 + -10; | |
| }); | |
| }); | |
| var weights = []; | |
| var head = []; | |
| var tail = []; | |
| for (var i = 0; i < graph.nRows; i++) { | |
| for (var j = 0; j < graph.nCols; j++) { | |
| var value = graph.get(i, j); | |
| if (value) { | |
| weights.push(value); | |
| tail.push(i); | |
| head.push(j); | |
| } | |
| } | |
| } | |
| var epochsPerSample = this.makeEpochsPerSample(weights, nEpochs); | |
| return { head: head, tail: tail, epochsPerSample: epochsPerSample }; | |
| }; | |
| UMAP.prototype.makeEpochsPerSample = function (weights, nEpochs) { | |
| var result = utils.filled(weights.length, -1.0); | |
| var max = utils.max(weights); | |
| var nSamples = weights.map(function (w) { return (w / max) * nEpochs; }); | |
| nSamples.forEach(function (n, i) { | |
| if (n > 0) | |
| result[i] = nEpochs / nSamples[i]; | |
| }); | |
| return result; | |
| }; | |
| UMAP.prototype.assignOptimizationStateParameters = function (state) { | |
| Object.assign(this.optimizationState, state); | |
| }; | |
| UMAP.prototype.prepareForOptimizationLoop = function () { | |
| var _a = this, repulsionStrength = _a.repulsionStrength, learningRate = _a.learningRate, negativeSampleRate = _a.negativeSampleRate; | |
| var _b = this.optimizationState, epochsPerSample = _b.epochsPerSample, headEmbedding = _b.headEmbedding, tailEmbedding = _b.tailEmbedding; | |
| var dim = headEmbedding[0].length; | |
| var moveOther = headEmbedding.length === tailEmbedding.length; | |
| var epochsPerNegativeSample = epochsPerSample.map(function (e) { return e / negativeSampleRate; }); | |
| var epochOfNextNegativeSample = __spread(epochsPerNegativeSample); | |
| var epochOfNextSample = __spread(epochsPerSample); | |
| this.assignOptimizationStateParameters({ | |
| epochOfNextSample: epochOfNextSample, | |
| epochOfNextNegativeSample: epochOfNextNegativeSample, | |
| epochsPerNegativeSample: epochsPerNegativeSample, | |
| moveOther: moveOther, | |
| initialAlpha: learningRate, | |
| alpha: learningRate, | |
| gamma: repulsionStrength, | |
| dim: dim, | |
| }); | |
| }; | |
| UMAP.prototype.initializeOptimization = function () { | |
| var headEmbedding = this.embedding; | |
| var tailEmbedding = this.embedding; | |
| var _a = this.optimizationState, head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample; | |
| var nEpochs = this.getNEpochs(); | |
| var nVertices = this.graph.nCols; | |
| var _b = findABParams(this.spread, this.minDist), a = _b.a, b = _b.b; | |
| this.assignOptimizationStateParameters({ | |
| headEmbedding: headEmbedding, | |
| tailEmbedding: tailEmbedding, | |
| head: head, | |
| tail: tail, | |
| epochsPerSample: epochsPerSample, | |
| a: a, | |
| b: b, | |
| nEpochs: nEpochs, | |
| nVertices: nVertices, | |
| }); | |
| }; | |
| UMAP.prototype.optimizeLayoutStep = function (n) { | |
| var optimizationState = this.optimizationState; | |
| var head = optimizationState.head, tail = optimizationState.tail, headEmbedding = optimizationState.headEmbedding, tailEmbedding = optimizationState.tailEmbedding, epochsPerSample = optimizationState.epochsPerSample, epochOfNextSample = optimizationState.epochOfNextSample, epochOfNextNegativeSample = optimizationState.epochOfNextNegativeSample, epochsPerNegativeSample = optimizationState.epochsPerNegativeSample, moveOther = optimizationState.moveOther, initialAlpha = optimizationState.initialAlpha, alpha = optimizationState.alpha, gamma = optimizationState.gamma, a = optimizationState.a, b = optimizationState.b, dim = optimizationState.dim, nEpochs = optimizationState.nEpochs, nVertices = optimizationState.nVertices; | |
| var clipValue = 4.0; | |
| for (var i = 0; i < epochsPerSample.length; i++) { | |
| if (epochOfNextSample[i] > n) { | |
| continue; | |
| } | |
| var j = head[i]; | |
| var k = tail[i]; | |
| var current = headEmbedding[j]; | |
| var other = tailEmbedding[k]; | |
| var distSquared = rDist(current, other); | |
| var gradCoeff = 0; | |
| if (distSquared > 0) { | |
| gradCoeff = -2.0 * a * b * Math.pow(distSquared, b - 1.0); | |
| gradCoeff /= a * Math.pow(distSquared, b) + 1.0; | |
| } | |
| for (var d = 0; d < dim; d++) { | |
| var gradD = clip(gradCoeff * (current[d] - other[d]), clipValue); | |
| current[d] += gradD * alpha; | |
| if (moveOther) { | |
| other[d] += -gradD * alpha; | |
| } | |
| } | |
| epochOfNextSample[i] += epochsPerSample[i]; | |
| var nNegSamples = Math.floor((n - epochOfNextNegativeSample[i]) / epochsPerNegativeSample[i]); | |
| for (var p = 0; p < nNegSamples; p++) { | |
| var k_1 = utils.tauRandInt(nVertices, this.random); | |
| var other_1 = tailEmbedding[k_1]; | |
| var distSquared_1 = rDist(current, other_1); | |
| var gradCoeff_1 = 0.0; | |
| if (distSquared_1 > 0.0) { | |
| gradCoeff_1 = 2.0 * gamma * b; | |
| gradCoeff_1 /= | |
| (0.001 + distSquared_1) * (a * Math.pow(distSquared_1, b) + 1); | |
| } | |
| else if (j === k_1) { | |
| continue; | |
| } | |
| for (var d = 0; d < dim; d++) { | |
| var gradD = 4.0; | |
| if (gradCoeff_1 > 0.0) { | |
| gradD = clip(gradCoeff_1 * (current[d] - other_1[d]), clipValue); | |
| } | |
| current[d] += gradD * alpha; | |
| } | |
| } | |
| epochOfNextNegativeSample[i] += nNegSamples * epochsPerNegativeSample[i]; | |
| } | |
| optimizationState.alpha = initialAlpha * (1.0 - n / nEpochs); | |
| optimizationState.currentEpoch += 1; | |
| return headEmbedding; | |
| }; | |
| UMAP.prototype.optimizeLayoutAsync = function (epochCallback) { | |
| var _this = this; | |
| if (epochCallback === void 0) { epochCallback = function () { return true; }; } | |
| return new Promise(function (resolve, reject) { | |
| var step = function () { return __awaiter(_this, void 0, void 0, function () { | |
| var _a, nEpochs, currentEpoch, epochCompleted, shouldStop, isFinished; | |
| return __generator(this, function (_b) { | |
| try { | |
| _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch; | |
| this.embedding = this.optimizeLayoutStep(currentEpoch); | |
| epochCompleted = this.optimizationState.currentEpoch; | |
| shouldStop = epochCallback(epochCompleted) === false; | |
| isFinished = epochCompleted === nEpochs; | |
| if (!shouldStop && !isFinished) { | |
| step(); | |
| } | |
| else { | |
| return [2, resolve(isFinished)]; | |
| } | |
| } | |
| catch (err) { | |
| reject(err); | |
| } | |
| return [2]; | |
| }); | |
| }); }; | |
| step(); | |
| }); | |
| }; | |
| UMAP.prototype.optimizeLayout = function (epochCallback) { | |
| if (epochCallback === void 0) { epochCallback = function () { return true; }; } | |
| var isFinished = false; | |
| var embedding = []; | |
| while (!isFinished) { | |
| var _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch; | |
| embedding = this.optimizeLayoutStep(currentEpoch); | |
| var epochCompleted = this.optimizationState.currentEpoch; | |
| var shouldStop = epochCallback(epochCompleted) === false; | |
| isFinished = epochCompleted === nEpochs || shouldStop; | |
| } | |
| return embedding; | |
| }; | |
| UMAP.prototype.getNEpochs = function () { | |
| var graph = this.graph; | |
| if (this.nEpochs > 0) { | |
| return this.nEpochs; | |
| } | |
| var length = graph.nRows; | |
| if (length <= 2500) { | |
| return 500; | |
| } | |
| else if (length <= 5000) { | |
| return 400; | |
| } | |
| else if (length <= 7500) { | |
| return 300; | |
| } | |
| else { | |
| return 200; | |
| } | |
| }; | |
| return UMAP; | |
| }()); | |
| exports.UMAP = UMAP; | |
| function euclidean(x, y) { | |
| var result = 0; | |
| for (var i = 0; i < x.length; i++) { | |
| result += Math.pow((x[i] - y[i]), 2); | |
| } | |
| return Math.sqrt(result); | |
| } | |
| exports.euclidean = euclidean; | |
| function cosine(x, y) { | |
| var result = 0.0; | |
| var normX = 0.0; | |
| var normY = 0.0; | |
| for (var i = 0; i < x.length; i++) { | |
| result += x[i] * y[i]; | |
| normX += Math.pow(x[i], 2); | |
| normY += Math.pow(y[i], 2); | |
| } | |
| if (normX === 0 && normY === 0) { | |
| return 0; | |
| } | |
| else if (normX === 0 || normY === 0) { | |
| return 1.0; | |
| } | |
| else { | |
| return 1.0 - result / Math.sqrt(normX * normY); | |
| } | |
| } | |
| exports.cosine = cosine; | |
| var OptimizationState = (function () { | |
| function OptimizationState() { | |
| this.currentEpoch = 0; | |
| this.headEmbedding = []; | |
| this.tailEmbedding = []; | |
| this.head = []; | |
| this.tail = []; | |
| this.epochsPerSample = []; | |
| this.epochOfNextSample = []; | |
| this.epochOfNextNegativeSample = []; | |
| this.epochsPerNegativeSample = []; | |
| this.moveOther = true; | |
| this.initialAlpha = 1.0; | |
| this.alpha = 1.0; | |
| this.gamma = 1.0; | |
| this.a = 1.5769434603113077; | |
| this.b = 0.8950608779109733; | |
| this.dim = 2; | |
| this.nEpochs = 500; | |
| this.nVertices = 0; | |
| } | |
| return OptimizationState; | |
| }()); | |
| function clip(x, clipValue) { | |
| if (x > clipValue) | |
| return clipValue; | |
| else if (x < -clipValue) | |
| return -clipValue; | |
| else | |
| return x; | |
| } | |
| function rDist(x, y) { | |
| var result = 0.0; | |
| for (var i = 0; i < x.length; i++) { | |
| result += Math.pow(x[i] - y[i], 2); | |
| } | |
| return result; | |
| } | |
| function findABParams(spread, minDist) { | |
| var curve = function (_a) { | |
| var _b = __read(_a, 2), a = _b[0], b = _b[1]; | |
| return function (x) { | |
| return 1.0 / (1.0 + a * Math.pow(x, (2 * b))); | |
| }; | |
| }; | |
| var xv = utils | |
| .linear(0, spread * 3, 300) | |
| .map(function (val) { return (val < minDist ? 1.0 : val); }); | |
| var yv = utils.zeros(xv.length).map(function (val, index) { | |
| var gte = xv[index] >= minDist; | |
| return gte ? Math.exp(-(xv[index] - minDist) / spread) : val; | |
| }); | |
| var initialValues = [0.5, 0.5]; | |
| var data = { x: xv, y: yv }; | |
| var options = { | |
| damping: 1.5, | |
| initialValues: initialValues, | |
| gradientDifference: 10e-2, | |
| maxIterations: 100, | |
| errorTolerance: 10e-3, | |
| }; | |
| var parameterValues = ml_levenberg_marquardt_1.default(data, curve, options).parameterValues; | |
| var _a = __read(parameterValues, 2), a = _a[0], b = _a[1]; | |
| return { a: a, b: b }; | |
| } | |
| exports.findABParams = findABParams; | |
| function fastIntersection(graph, target, unknownDist, farDist) { | |
| if (unknownDist === void 0) { unknownDist = 1.0; } | |
| if (farDist === void 0) { farDist = 5.0; } | |
| return graph.map(function (value, row, col) { | |
| if (target[row] === -1 || target[col] === -1) { | |
| return value * Math.exp(-unknownDist); | |
| } | |
| else if (target[row] !== target[col]) { | |
| return value * Math.exp(-farDist); | |
| } | |
| else { | |
| return value; | |
| } | |
| }); | |
| } | |
| exports.fastIntersection = fastIntersection; | |
| function resetLocalConnectivity(simplicialSet) { | |
| simplicialSet = matrix.normalize(simplicialSet, "max"); | |
| var transpose = matrix.transpose(simplicialSet); | |
| var prodMatrix = matrix.pairwiseMultiply(transpose, simplicialSet); | |
| simplicialSet = matrix.add(simplicialSet, matrix.subtract(transpose, prodMatrix)); | |
| return matrix.eliminateZeros(simplicialSet); | |
| } | |
| exports.resetLocalConnectivity = resetLocalConnectivity; | |
| function initTransform(indices, weights, embedding) { | |
| var result = utils | |
| .zeros(indices.length) | |
| .map(function (z) { return utils.zeros(embedding[0].length); }); | |
| for (var i = 0; i < indices.length; i++) { | |
| for (var j = 0; j < indices[0].length; j++) { | |
| for (var d = 0; d < embedding[0].length; d++) { | |
| var a = indices[i][j]; | |
| result[i][d] += weights[i][j] * embedding[a][d]; | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| exports.initTransform = initTransform; | |
| /***/ }), | |
| /* 7 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var __values = (this && this.__values) || function (o) { | |
| var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | |
| if (m) return m.call(o); | |
| return { | |
| next: function () { | |
| if (o && i >= o.length) o = void 0; | |
| return { value: o && o[i++], done: !o }; | |
| } | |
| }; | |
| }; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | |
| result["default"] = mod; | |
| return result; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| var heap = __importStar(__webpack_require__(2)); | |
| var matrix = __importStar(__webpack_require__(3)); | |
| var tree = __importStar(__webpack_require__(4)); | |
| var utils = __importStar(__webpack_require__(1)); | |
| function makeNNDescent(distanceFn, random) { | |
| return function nNDescent(data, leafArray, nNeighbors, nIters, maxCandidates, delta, rho, rpTreeInit) { | |
| if (nIters === void 0) { nIters = 10; } | |
| if (maxCandidates === void 0) { maxCandidates = 50; } | |
| if (delta === void 0) { delta = 0.001; } | |
| if (rho === void 0) { rho = 0.5; } | |
| if (rpTreeInit === void 0) { rpTreeInit = true; } | |
| var nVertices = data.length; | |
| var currentGraph = heap.makeHeap(data.length, nNeighbors); | |
| for (var i = 0; i < data.length; i++) { | |
| var indices = heap.rejectionSample(nNeighbors, data.length, random); | |
| for (var j = 0; j < indices.length; j++) { | |
| var d = distanceFn(data[i], data[indices[j]]); | |
| heap.heapPush(currentGraph, i, d, indices[j], 1); | |
| heap.heapPush(currentGraph, indices[j], d, i, 1); | |
| } | |
| } | |
| if (rpTreeInit) { | |
| for (var n = 0; n < leafArray.length; n++) { | |
| for (var i = 0; i < leafArray[n].length; i++) { | |
| if (leafArray[n][i] < 0) { | |
| break; | |
| } | |
| for (var j = i + 1; j < leafArray[n].length; j++) { | |
| if (leafArray[n][j] < 0) { | |
| break; | |
| } | |
| var d = distanceFn(data[leafArray[n][i]], data[leafArray[n][j]]); | |
| heap.heapPush(currentGraph, leafArray[n][i], d, leafArray[n][j], 1); | |
| heap.heapPush(currentGraph, leafArray[n][j], d, leafArray[n][i], 1); | |
| } | |
| } | |
| } | |
| } | |
| for (var n = 0; n < nIters; n++) { | |
| var candidateNeighbors = heap.buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random); | |
| var c = 0; | |
| for (var i = 0; i < nVertices; i++) { | |
| for (var j = 0; j < maxCandidates; j++) { | |
| var p = Math.floor(candidateNeighbors[0][i][j]); | |
| if (p < 0 || utils.tauRand(random) < rho) { | |
| continue; | |
| } | |
| for (var k = 0; k < maxCandidates; k++) { | |
| var q = Math.floor(candidateNeighbors[0][i][k]); | |
| var cj = candidateNeighbors[2][i][j]; | |
| var ck = candidateNeighbors[2][i][k]; | |
| if (q < 0 || (!cj && !ck)) { | |
| continue; | |
| } | |
| var d = distanceFn(data[p], data[q]); | |
| c += heap.heapPush(currentGraph, p, d, q, 1); | |
| c += heap.heapPush(currentGraph, q, d, p, 1); | |
| } | |
| } | |
| } | |
| if (c <= delta * nNeighbors * data.length) { | |
| break; | |
| } | |
| } | |
| var sorted = heap.deheapSort(currentGraph); | |
| return sorted; | |
| }; | |
| } | |
| exports.makeNNDescent = makeNNDescent; | |
| function makeInitializations(distanceFn) { | |
| function initFromRandom(nNeighbors, data, queryPoints, _heap, random) { | |
| for (var i = 0; i < queryPoints.length; i++) { | |
| var indices = utils.rejectionSample(nNeighbors, data.length, random); | |
| for (var j = 0; j < indices.length; j++) { | |
| if (indices[j] < 0) { | |
| continue; | |
| } | |
| var d = distanceFn(data[indices[j]], queryPoints[i]); | |
| heap.heapPush(_heap, i, d, indices[j], 1); | |
| } | |
| } | |
| } | |
| function initFromTree(_tree, data, queryPoints, _heap, random) { | |
| for (var i = 0; i < queryPoints.length; i++) { | |
| var indices = tree.searchFlatTree(queryPoints[i], _tree, random); | |
| for (var j = 0; j < indices.length; j++) { | |
| if (indices[j] < 0) { | |
| return; | |
| } | |
| var d = distanceFn(data[indices[j]], queryPoints[i]); | |
| heap.heapPush(_heap, i, d, indices[j], 1); | |
| } | |
| } | |
| return; | |
| } | |
| return { initFromRandom: initFromRandom, initFromTree: initFromTree }; | |
| } | |
| exports.makeInitializations = makeInitializations; | |
| function makeInitializedNNSearch(distanceFn) { | |
| return function nnSearchFn(data, graph, initialization, queryPoints) { | |
| var e_1, _a; | |
| var _b = matrix.getCSR(graph), indices = _b.indices, indptr = _b.indptr; | |
| for (var i = 0; i < queryPoints.length; i++) { | |
| var tried = new Set(initialization[0][i]); | |
| while (true) { | |
| var vertex = heap.smallestFlagged(initialization, i); | |
| if (vertex === -1) { | |
| break; | |
| } | |
| var candidates = indices.slice(indptr[vertex], indptr[vertex + 1]); | |
| try { | |
| for (var candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) { | |
| var candidate = candidates_1_1.value; | |
| if (candidate === vertex || | |
| candidate === -1 || | |
| tried.has(candidate)) { | |
| continue; | |
| } | |
| var d = distanceFn(data[candidate], queryPoints[i]); | |
| heap.uncheckedHeapPush(initialization, i, d, candidate, 1); | |
| tried.add(candidate); | |
| } | |
| } | |
| catch (e_1_1) { e_1 = { error: e_1_1 }; } | |
| finally { | |
| try { | |
| if (candidates_1_1 && !candidates_1_1.done && (_a = candidates_1.return)) _a.call(candidates_1); | |
| } | |
| finally { if (e_1) throw e_1.error; } | |
| } | |
| } | |
| } | |
| return initialization; | |
| }; | |
| } | |
| exports.makeInitializedNNSearch = makeInitializedNNSearch; | |
| function initializeSearch(forest, data, queryPoints, nNeighbors, initFromRandom, initFromTree, random) { | |
| var e_2, _a; | |
| var results = heap.makeHeap(queryPoints.length, nNeighbors); | |
| initFromRandom(nNeighbors, data, queryPoints, results, random); | |
| if (forest) { | |
| try { | |
| for (var forest_1 = __values(forest), forest_1_1 = forest_1.next(); !forest_1_1.done; forest_1_1 = forest_1.next()) { | |
| var tree_1 = forest_1_1.value; | |
| initFromTree(tree_1, data, queryPoints, results, random); | |
| } | |
| } | |
| catch (e_2_1) { e_2 = { error: e_2_1 }; } | |
| finally { | |
| try { | |
| if (forest_1_1 && !forest_1_1.done && (_a = forest_1.return)) _a.call(forest_1); | |
| } | |
| finally { if (e_2) throw e_2.error; } | |
| } | |
| } | |
| return results; | |
| } | |
| exports.initializeSearch = initializeSearch; | |
| /***/ }), | |
| /* 8 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| var mlMatrix = __webpack_require__(9); | |
| /** | |
| * Calculate current error | |
| * @ignore | |
| * @param {{x:Array<number>, y:Array<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ] | |
| * @param {Array<number>} parameters - Array of current parameter values | |
| * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter | |
| * @return {number} | |
| */ | |
| function errorCalculation( | |
| data, | |
| parameters, | |
| parameterizedFunction | |
| ) { | |
| var error = 0; | |
| const func = parameterizedFunction(parameters); | |
| for (var i = 0; i < data.x.length; i++) { | |
| error += Math.abs(data.y[i] - func(data.x[i])); | |
| } | |
| return error; | |
| } | |
| /** | |
| * Difference of the matrix function over the parameters | |
| * @ignore | |
| * @param {{x:Array<number>, y:Array<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ] | |
| * @param {Array<number>} evaluatedData - Array of previous evaluated function values | |
| * @param {Array<number>} params - Array of previous parameter values | |
| * @param {number} gradientDifference - Adjustment for decrease the damping parameter | |
| * @param {function} paramFunction - The parameters and returns a function with the independent variable as a parameter | |
| * @return {Matrix} | |
| */ | |
| function gradientFunction( | |
| data, | |
| evaluatedData, | |
| params, | |
| gradientDifference, | |
| paramFunction | |
| ) { | |
| const n = params.length; | |
| const m = data.x.length; | |
| var ans = new Array(n); | |
| for (var param = 0; param < n; param++) { | |
| ans[param] = new Array(m); | |
| var auxParams = params.concat(); | |
| auxParams[param] += gradientDifference; | |
| var funcParam = paramFunction(auxParams); | |
| for (var point = 0; point < m; point++) { | |
| ans[param][point] = evaluatedData[point] - funcParam(data.x[point]); | |
| } | |
| } | |
| return new mlMatrix.Matrix(ans); | |
| } | |
| /** | |
| * Matrix function over the samples | |
| * @ignore | |
| * @param {{x:Array<number>, y:Array<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ] | |
| * @param {Array<number>} evaluatedData - Array of previous evaluated function values | |
| * @return {Matrix} | |
| */ | |
| function matrixFunction(data, evaluatedData) { | |
| const m = data.x.length; | |
| var ans = new Array(m); | |
| for (var point = 0; point < m; point++) { | |
| ans[point] = data.y[point] - evaluatedData[point]; | |
| } | |
| return new mlMatrix.Matrix([ans]); | |
| } | |
| /** | |
| * Iteration for Levenberg-Marquardt | |
| * @ignore | |
| * @param {{x:Array<number>, y:Array<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ] | |
| * @param {Array<number>} params - Array of previous parameter values | |
| * @param {number} damping - Levenberg-Marquardt parameter | |
| * @param {number} gradientDifference - Adjustment for decrease the damping parameter | |
| * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter | |
| * @return {Array<number>} | |
| */ | |
| function step( | |
| data, | |
| params, | |
| damping, | |
| gradientDifference, | |
| parameterizedFunction | |
| ) { | |
| var identity = mlMatrix.Matrix.eye(params.length).mul( | |
| damping * gradientDifference * gradientDifference | |
| ); | |
| var l = data.x.length; | |
| var evaluatedData = new Array(l); | |
| const func = parameterizedFunction(params); | |
| for (var i = 0; i < l; i++) { | |
| evaluatedData[i] = func(data.x[i]); | |
| } | |
| var gradientFunc = gradientFunction( | |
| data, | |
| evaluatedData, | |
| params, | |
| gradientDifference, | |
| parameterizedFunction | |
| ); | |
| var matrixFunc = matrixFunction(data, evaluatedData).transposeView(); | |
| var inverseMatrix = mlMatrix.inverse( | |
| identity.add(gradientFunc.mmul(gradientFunc.transposeView())) | |
| ); | |
| params = new mlMatrix.Matrix([params]); | |
| params = params.sub( | |
| inverseMatrix | |
| .mmul(gradientFunc) | |
| .mmul(matrixFunc) | |
| .mul(gradientDifference) | |
| .transposeView() | |
| ); | |
| return params.to1DArray(); | |
| } | |
| /** | |
| * Curve fitting algorithm | |
| * @param {{x:Array<number>, y:Array<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ] | |
| * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter | |
| * @param {object} [options] - Options object | |
| * @param {number} [options.damping] - Levenberg-Marquardt parameter | |
| * @param {number} [options.gradientDifference = 10e-2] - Adjustment for decrease the damping parameter | |
| * @param {Array<number>} [options.initialValues] - Array of initial parameter values | |
| * @param {number} [options.maxIterations = 100] - Maximum of allowed iterations | |
| * @param {number} [options.errorTolerance = 10e-3] - Minimum uncertainty allowed for each point | |
| * @return {{parameterValues: Array<number>, parameterError: number, iterations: number}} | |
| */ | |
| function levenbergMarquardt( | |
| data, | |
| parameterizedFunction, | |
| options = {} | |
| ) { | |
| let { | |
| maxIterations = 100, | |
| gradientDifference = 10e-2, | |
| damping = 0, | |
| errorTolerance = 10e-3, | |
| initialValues | |
| } = options; | |
| if (damping <= 0) { | |
| throw new Error('The damping option must be a positive number'); | |
| } else if (!data.x || !data.y) { | |
| throw new Error('The data parameter must have x and y elements'); | |
| } else if ( | |
| !Array.isArray(data.x) || | |
| data.x.length < 2 || | |
| !Array.isArray(data.y) || | |
| data.y.length < 2 | |
| ) { | |
| throw new Error( | |
| 'The data parameter elements must be an array with more than 2 points' | |
| ); | |
| } else { | |
| let dataLen = data.x.length; | |
| if (dataLen !== data.y.length) { | |
| throw new Error('The data parameter elements must have the same size'); | |
| } | |
| } | |
| var parameters = | |
| initialValues || new Array(parameterizedFunction.length).fill(1); | |
| if (!Array.isArray(parameters)) { | |
| throw new Error('initialValues must be an array'); | |
| } | |
| var error = errorCalculation(data, parameters, parameterizedFunction); | |
| var converged = error <= errorTolerance; | |
| for ( | |
| var iteration = 0; | |
| iteration < maxIterations && !converged; | |
| iteration++ | |
| ) { | |
| parameters = step( | |
| data, | |
| parameters, | |
| damping, | |
| gradientDifference, | |
| parameterizedFunction | |
| ); | |
| error = errorCalculation(data, parameters, parameterizedFunction); | |
| converged = error <= errorTolerance; | |
| } | |
| return { | |
| parameterValues: parameters, | |
| parameterError: error, | |
| iterations: iteration | |
| }; | |
| } | |
| module.exports = levenbergMarquardt; | |
| /***/ }), | |
| /* 9 */ | |
| /***/ (function(module, __webpack_exports__, __webpack_require__) { | |
| ; | |
| __webpack_require__.r(__webpack_exports__); | |
| // EXTERNAL MODULE: ./node_modules/is-any-array/src/index.js | |
| var src = __webpack_require__(0); | |
| var src_default = /*#__PURE__*/__webpack_require__.n(src); | |
| // CONCATENATED MODULE: ./node_modules/ml-array-max/lib-es6/index.js | |
| /** | |
| * Computes the maximum of the given values | |
| * @param {Array<number>} input | |
| * @return {number} | |
| */ | |
| function lib_es6_max(input) { | |
| if (!src_default()(input)) { | |
| throw new TypeError('input must be an array'); | |
| } | |
| if (input.length === 0) { | |
| throw new TypeError('input must not be empty'); | |
| } | |
| var max = input[0]; | |
| for (var i = 1; i < input.length; i++) { | |
| if (input[i] > max) max = input[i]; | |
| } | |
| return max; | |
| } | |
| /* harmony default export */ var lib_es6 = (lib_es6_max); | |
| // CONCATENATED MODULE: ./node_modules/ml-array-min/lib-es6/index.js | |
| /** | |
| * Computes the minimum of the given values | |
| * @param {Array<number>} input | |
| * @return {number} | |
| */ | |
| function lib_es6_min(input) { | |
| if (!src_default()(input)) { | |
| throw new TypeError('input must be an array'); | |
| } | |
| if (input.length === 0) { | |
| throw new TypeError('input must not be empty'); | |
| } | |
| var min = input[0]; | |
| for (var i = 1; i < input.length; i++) { | |
| if (input[i] < min) min = input[i]; | |
| } | |
| return min; | |
| } | |
| /* harmony default export */ var ml_array_min_lib_es6 = (lib_es6_min); | |
| // CONCATENATED MODULE: ./node_modules/ml-array-rescale/lib-es6/index.js | |
| function rescale(input) { | |
| var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
| if (!src_default()(input)) { | |
| throw new TypeError('input must be an array'); | |
| } else if (input.length === 0) { | |
| throw new TypeError('input must not be empty'); | |
| } | |
| var output; | |
| if (options.output !== undefined) { | |
| if (!src_default()(options.output)) { | |
| throw new TypeError('output option must be an array if specified'); | |
| } | |
| output = options.output; | |
| } else { | |
| output = new Array(input.length); | |
| } | |
| var currentMin = ml_array_min_lib_es6(input); | |
| var currentMax = lib_es6(input); | |
| if (currentMin === currentMax) { | |
| throw new RangeError('minimum and maximum input values are equal. Cannot rescale a constant array'); | |
| } | |
| var _options$min = options.min, | |
| minValue = _options$min === void 0 ? options.autoMinMax ? currentMin : 0 : _options$min, | |
| _options$max = options.max, | |
| maxValue = _options$max === void 0 ? options.autoMinMax ? currentMax : 1 : _options$max; | |
| if (minValue >= maxValue) { | |
| throw new RangeError('min option must be smaller than max option'); | |
| } | |
| var factor = (maxValue - minValue) / (currentMax - currentMin); | |
| for (var i = 0; i < input.length; i++) { | |
| output[i] = (input[i] - currentMin) * factor + minValue; | |
| } | |
| return output; | |
| } | |
| /* harmony default export */ var ml_array_rescale_lib_es6 = (rescale); | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/lu.js | |
| /** | |
| * @class LuDecomposition | |
| * @link https://github.com/lutzroeder/Mapack/blob/master/Source/LuDecomposition.cs | |
| * @param {Matrix} matrix | |
| */ | |
| class lu_LuDecomposition { | |
| constructor(matrix) { | |
| matrix = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(matrix); | |
| var lu = matrix.clone(); | |
| var rows = lu.rows; | |
| var columns = lu.columns; | |
| var pivotVector = new Array(rows); | |
| var pivotSign = 1; | |
| var i, j, k, p, s, t, v; | |
| var LUcolj, kmax; | |
| for (i = 0; i < rows; i++) { | |
| pivotVector[i] = i; | |
| } | |
| LUcolj = new Array(rows); | |
| for (j = 0; j < columns; j++) { | |
| for (i = 0; i < rows; i++) { | |
| LUcolj[i] = lu.get(i, j); | |
| } | |
| for (i = 0; i < rows; i++) { | |
| kmax = Math.min(i, j); | |
| s = 0; | |
| for (k = 0; k < kmax; k++) { | |
| s += lu.get(i, k) * LUcolj[k]; | |
| } | |
| LUcolj[i] -= s; | |
| lu.set(i, j, LUcolj[i]); | |
| } | |
| p = j; | |
| for (i = j + 1; i < rows; i++) { | |
| if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) { | |
| p = i; | |
| } | |
| } | |
| if (p !== j) { | |
| for (k = 0; k < columns; k++) { | |
| t = lu.get(p, k); | |
| lu.set(p, k, lu.get(j, k)); | |
| lu.set(j, k, t); | |
| } | |
| v = pivotVector[p]; | |
| pivotVector[p] = pivotVector[j]; | |
| pivotVector[j] = v; | |
| pivotSign = -pivotSign; | |
| } | |
| if (j < rows && lu.get(j, j) !== 0) { | |
| for (i = j + 1; i < rows; i++) { | |
| lu.set(i, j, lu.get(i, j) / lu.get(j, j)); | |
| } | |
| } | |
| } | |
| this.LU = lu; | |
| this.pivotVector = pivotVector; | |
| this.pivotSign = pivotSign; | |
| } | |
| /** | |
| * | |
| * @return {boolean} | |
| */ | |
| isSingular() { | |
| var data = this.LU; | |
| var col = data.columns; | |
| for (var j = 0; j < col; j++) { | |
| if (data[j][j] === 0) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| /** | |
| * | |
| * @param {Matrix} value | |
| * @return {Matrix} | |
| */ | |
| solve(value) { | |
| value = matrix_Matrix.checkMatrix(value); | |
| var lu = this.LU; | |
| var rows = lu.rows; | |
| if (rows !== value.rows) { | |
| throw new Error('Invalid matrix dimensions'); | |
| } | |
| if (this.isSingular()) { | |
| throw new Error('LU matrix is singular'); | |
| } | |
| var count = value.columns; | |
| var X = value.subMatrixRow(this.pivotVector, 0, count - 1); | |
| var columns = lu.columns; | |
| var i, j, k; | |
| for (k = 0; k < columns; k++) { | |
| for (i = k + 1; i < columns; i++) { | |
| for (j = 0; j < count; j++) { | |
| X[i][j] -= X[k][j] * lu[i][k]; | |
| } | |
| } | |
| } | |
| for (k = columns - 1; k >= 0; k--) { | |
| for (j = 0; j < count; j++) { | |
| X[k][j] /= lu[k][k]; | |
| } | |
| for (i = 0; i < k; i++) { | |
| for (j = 0; j < count; j++) { | |
| X[i][j] -= X[k][j] * lu[i][k]; | |
| } | |
| } | |
| } | |
| return X; | |
| } | |
| /** | |
| * | |
| * @return {number} | |
| */ | |
| get determinant() { | |
| var data = this.LU; | |
| if (!data.isSquare()) { | |
| throw new Error('Matrix must be square'); | |
| } | |
| var determinant = this.pivotSign; | |
| var col = data.columns; | |
| for (var j = 0; j < col; j++) { | |
| determinant *= data[j][j]; | |
| } | |
| return determinant; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get lowerTriangularMatrix() { | |
| var data = this.LU; | |
| var rows = data.rows; | |
| var columns = data.columns; | |
| var X = new matrix_Matrix(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| if (i > j) { | |
| X[i][j] = data[i][j]; | |
| } else if (i === j) { | |
| X[i][j] = 1; | |
| } else { | |
| X[i][j] = 0; | |
| } | |
| } | |
| } | |
| return X; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get upperTriangularMatrix() { | |
| var data = this.LU; | |
| var rows = data.rows; | |
| var columns = data.columns; | |
| var X = new matrix_Matrix(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| if (i <= j) { | |
| X[i][j] = data[i][j]; | |
| } else { | |
| X[i][j] = 0; | |
| } | |
| } | |
| } | |
| return X; | |
| } | |
| /** | |
| * | |
| * @return {Array<number>} | |
| */ | |
| get pivotPermutationVector() { | |
| return this.pivotVector.slice(); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/util.js | |
| function hypotenuse(a, b) { | |
| var r = 0; | |
| if (Math.abs(a) > Math.abs(b)) { | |
| r = b / a; | |
| return Math.abs(a) * Math.sqrt(1 + r * r); | |
| } | |
| if (b !== 0) { | |
| r = a / b; | |
| return Math.abs(b) * Math.sqrt(1 + r * r); | |
| } | |
| return 0; | |
| } | |
| function getFilled2DArray(rows, columns, value) { | |
| var array = new Array(rows); | |
| for (var i = 0; i < rows; i++) { | |
| array[i] = new Array(columns); | |
| for (var j = 0; j < columns; j++) { | |
| array[i][j] = value; | |
| } | |
| } | |
| return array; | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/svd.js | |
| /** | |
| * @class SingularValueDecomposition | |
| * @see https://github.com/accord-net/framework/blob/development/Sources/Accord.Math/Decompositions/SingularValueDecomposition.cs | |
| * @param {Matrix} value | |
| * @param {object} [options] | |
| * @param {boolean} [options.computeLeftSingularVectors=true] | |
| * @param {boolean} [options.computeRightSingularVectors=true] | |
| * @param {boolean} [options.autoTranspose=false] | |
| */ | |
| class svd_SingularValueDecomposition { | |
| constructor(value, options = {}) { | |
| value = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(value); | |
| var m = value.rows; | |
| var n = value.columns; | |
| const { | |
| computeLeftSingularVectors = true, | |
| computeRightSingularVectors = true, | |
| autoTranspose = false | |
| } = options; | |
| var wantu = Boolean(computeLeftSingularVectors); | |
| var wantv = Boolean(computeRightSingularVectors); | |
| var swapped = false; | |
| var a; | |
| if (m < n) { | |
| if (!autoTranspose) { | |
| a = value.clone(); | |
| // eslint-disable-next-line no-console | |
| console.warn( | |
| 'Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose' | |
| ); | |
| } else { | |
| a = value.transpose(); | |
| m = a.rows; | |
| n = a.columns; | |
| swapped = true; | |
| var aux = wantu; | |
| wantu = wantv; | |
| wantv = aux; | |
| } | |
| } else { | |
| a = value.clone(); | |
| } | |
| var nu = Math.min(m, n); | |
| var ni = Math.min(m + 1, n); | |
| var s = new Array(ni); | |
| var U = getFilled2DArray(m, nu, 0); | |
| var V = getFilled2DArray(n, n, 0); | |
| var e = new Array(n); | |
| var work = new Array(m); | |
| var si = new Array(ni); | |
| for (let i = 0; i < ni; i++) si[i] = i; | |
| var nct = Math.min(m - 1, n); | |
| var nrt = Math.max(0, Math.min(n - 2, m)); | |
| var mrc = Math.max(nct, nrt); | |
| for (let k = 0; k < mrc; k++) { | |
| if (k < nct) { | |
| s[k] = 0; | |
| for (let i = k; i < m; i++) { | |
| s[k] = hypotenuse(s[k], a[i][k]); | |
| } | |
| if (s[k] !== 0) { | |
| if (a[k][k] < 0) { | |
| s[k] = -s[k]; | |
| } | |
| for (let i = k; i < m; i++) { | |
| a[i][k] /= s[k]; | |
| } | |
| a[k][k] += 1; | |
| } | |
| s[k] = -s[k]; | |
| } | |
| for (let j = k + 1; j < n; j++) { | |
| if (k < nct && s[k] !== 0) { | |
| let t = 0; | |
| for (let i = k; i < m; i++) { | |
| t += a[i][k] * a[i][j]; | |
| } | |
| t = -t / a[k][k]; | |
| for (let i = k; i < m; i++) { | |
| a[i][j] += t * a[i][k]; | |
| } | |
| } | |
| e[j] = a[k][j]; | |
| } | |
| if (wantu && k < nct) { | |
| for (let i = k; i < m; i++) { | |
| U[i][k] = a[i][k]; | |
| } | |
| } | |
| if (k < nrt) { | |
| e[k] = 0; | |
| for (let i = k + 1; i < n; i++) { | |
| e[k] = hypotenuse(e[k], e[i]); | |
| } | |
| if (e[k] !== 0) { | |
| if (e[k + 1] < 0) { | |
| e[k] = 0 - e[k]; | |
| } | |
| for (let i = k + 1; i < n; i++) { | |
| e[i] /= e[k]; | |
| } | |
| e[k + 1] += 1; | |
| } | |
| e[k] = -e[k]; | |
| if (k + 1 < m && e[k] !== 0) { | |
| for (let i = k + 1; i < m; i++) { | |
| work[i] = 0; | |
| } | |
| for (let i = k + 1; i < m; i++) { | |
| for (let j = k + 1; j < n; j++) { | |
| work[i] += e[j] * a[i][j]; | |
| } | |
| } | |
| for (let j = k + 1; j < n; j++) { | |
| let t = -e[j] / e[k + 1]; | |
| for (let i = k + 1; i < m; i++) { | |
| a[i][j] += t * work[i]; | |
| } | |
| } | |
| } | |
| if (wantv) { | |
| for (let i = k + 1; i < n; i++) { | |
| V[i][k] = e[i]; | |
| } | |
| } | |
| } | |
| } | |
| let p = Math.min(n, m + 1); | |
| if (nct < n) { | |
| s[nct] = a[nct][nct]; | |
| } | |
| if (m < p) { | |
| s[p - 1] = 0; | |
| } | |
| if (nrt + 1 < p) { | |
| e[nrt] = a[nrt][p - 1]; | |
| } | |
| e[p - 1] = 0; | |
| if (wantu) { | |
| for (let j = nct; j < nu; j++) { | |
| for (let i = 0; i < m; i++) { | |
| U[i][j] = 0; | |
| } | |
| U[j][j] = 1; | |
| } | |
| for (let k = nct - 1; k >= 0; k--) { | |
| if (s[k] !== 0) { | |
| for (let j = k + 1; j < nu; j++) { | |
| let t = 0; | |
| for (let i = k; i < m; i++) { | |
| t += U[i][k] * U[i][j]; | |
| } | |
| t = -t / U[k][k]; | |
| for (let i = k; i < m; i++) { | |
| U[i][j] += t * U[i][k]; | |
| } | |
| } | |
| for (let i = k; i < m; i++) { | |
| U[i][k] = -U[i][k]; | |
| } | |
| U[k][k] = 1 + U[k][k]; | |
| for (let i = 0; i < k - 1; i++) { | |
| U[i][k] = 0; | |
| } | |
| } else { | |
| for (let i = 0; i < m; i++) { | |
| U[i][k] = 0; | |
| } | |
| U[k][k] = 1; | |
| } | |
| } | |
| } | |
| if (wantv) { | |
| for (let k = n - 1; k >= 0; k--) { | |
| if (k < nrt && e[k] !== 0) { | |
| for (let j = k + 1; j < n; j++) { | |
| let t = 0; | |
| for (let i = k + 1; i < n; i++) { | |
| t += V[i][k] * V[i][j]; | |
| } | |
| t = -t / V[k + 1][k]; | |
| for (let i = k + 1; i < n; i++) { | |
| V[i][j] += t * V[i][k]; | |
| } | |
| } | |
| } | |
| for (let i = 0; i < n; i++) { | |
| V[i][k] = 0; | |
| } | |
| V[k][k] = 1; | |
| } | |
| } | |
| var pp = p - 1; | |
| var iter = 0; | |
| var eps = Number.EPSILON; | |
| while (p > 0) { | |
| let k, kase; | |
| for (k = p - 2; k >= -1; k--) { | |
| if (k === -1) { | |
| break; | |
| } | |
| const alpha = | |
| Number.MIN_VALUE + eps * Math.abs(s[k] + Math.abs(s[k + 1])); | |
| if (Math.abs(e[k]) <= alpha || Number.isNaN(e[k])) { | |
| e[k] = 0; | |
| break; | |
| } | |
| } | |
| if (k === p - 2) { | |
| kase = 4; | |
| } else { | |
| let ks; | |
| for (ks = p - 1; ks >= k; ks--) { | |
| if (ks === k) { | |
| break; | |
| } | |
| let t = | |
| (ks !== p ? Math.abs(e[ks]) : 0) + | |
| (ks !== k + 1 ? Math.abs(e[ks - 1]) : 0); | |
| if (Math.abs(s[ks]) <= eps * t) { | |
| s[ks] = 0; | |
| break; | |
| } | |
| } | |
| if (ks === k) { | |
| kase = 3; | |
| } else if (ks === p - 1) { | |
| kase = 1; | |
| } else { | |
| kase = 2; | |
| k = ks; | |
| } | |
| } | |
| k++; | |
| switch (kase) { | |
| case 1: { | |
| let f = e[p - 2]; | |
| e[p - 2] = 0; | |
| for (let j = p - 2; j >= k; j--) { | |
| let t = hypotenuse(s[j], f); | |
| let cs = s[j] / t; | |
| let sn = f / t; | |
| s[j] = t; | |
| if (j !== k) { | |
| f = -sn * e[j - 1]; | |
| e[j - 1] = cs * e[j - 1]; | |
| } | |
| if (wantv) { | |
| for (let i = 0; i < n; i++) { | |
| t = cs * V[i][j] + sn * V[i][p - 1]; | |
| V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1]; | |
| V[i][j] = t; | |
| } | |
| } | |
| } | |
| break; | |
| } | |
| case 2: { | |
| let f = e[k - 1]; | |
| e[k - 1] = 0; | |
| for (let j = k; j < p; j++) { | |
| let t = hypotenuse(s[j], f); | |
| let cs = s[j] / t; | |
| let sn = f / t; | |
| s[j] = t; | |
| f = -sn * e[j]; | |
| e[j] = cs * e[j]; | |
| if (wantu) { | |
| for (let i = 0; i < m; i++) { | |
| t = cs * U[i][j] + sn * U[i][k - 1]; | |
| U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1]; | |
| U[i][j] = t; | |
| } | |
| } | |
| } | |
| break; | |
| } | |
| case 3: { | |
| const scale = Math.max( | |
| Math.abs(s[p - 1]), | |
| Math.abs(s[p - 2]), | |
| Math.abs(e[p - 2]), | |
| Math.abs(s[k]), | |
| Math.abs(e[k]) | |
| ); | |
| const sp = s[p - 1] / scale; | |
| const spm1 = s[p - 2] / scale; | |
| const epm1 = e[p - 2] / scale; | |
| const sk = s[k] / scale; | |
| const ek = e[k] / scale; | |
| const b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; | |
| const c = sp * epm1 * (sp * epm1); | |
| let shift = 0; | |
| if (b !== 0 || c !== 0) { | |
| if (b < 0) { | |
| shift = 0 - Math.sqrt(b * b + c); | |
| } else { | |
| shift = Math.sqrt(b * b + c); | |
| } | |
| shift = c / (b + shift); | |
| } | |
| let f = (sk + sp) * (sk - sp) + shift; | |
| let g = sk * ek; | |
| for (let j = k; j < p - 1; j++) { | |
| let t = hypotenuse(f, g); | |
| if (t === 0) t = Number.MIN_VALUE; | |
| let cs = f / t; | |
| let sn = g / t; | |
| if (j !== k) { | |
| e[j - 1] = t; | |
| } | |
| f = cs * s[j] + sn * e[j]; | |
| e[j] = cs * e[j] - sn * s[j]; | |
| g = sn * s[j + 1]; | |
| s[j + 1] = cs * s[j + 1]; | |
| if (wantv) { | |
| for (let i = 0; i < n; i++) { | |
| t = cs * V[i][j] + sn * V[i][j + 1]; | |
| V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1]; | |
| V[i][j] = t; | |
| } | |
| } | |
| t = hypotenuse(f, g); | |
| if (t === 0) t = Number.MIN_VALUE; | |
| cs = f / t; | |
| sn = g / t; | |
| s[j] = t; | |
| f = cs * e[j] + sn * s[j + 1]; | |
| s[j + 1] = -sn * e[j] + cs * s[j + 1]; | |
| g = sn * e[j + 1]; | |
| e[j + 1] = cs * e[j + 1]; | |
| if (wantu && j < m - 1) { | |
| for (let i = 0; i < m; i++) { | |
| t = cs * U[i][j] + sn * U[i][j + 1]; | |
| U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1]; | |
| U[i][j] = t; | |
| } | |
| } | |
| } | |
| e[p - 2] = f; | |
| iter = iter + 1; | |
| break; | |
| } | |
| case 4: { | |
| if (s[k] <= 0) { | |
| s[k] = s[k] < 0 ? -s[k] : 0; | |
| if (wantv) { | |
| for (let i = 0; i <= pp; i++) { | |
| V[i][k] = -V[i][k]; | |
| } | |
| } | |
| } | |
| while (k < pp) { | |
| if (s[k] >= s[k + 1]) { | |
| break; | |
| } | |
| let t = s[k]; | |
| s[k] = s[k + 1]; | |
| s[k + 1] = t; | |
| if (wantv && k < n - 1) { | |
| for (let i = 0; i < n; i++) { | |
| t = V[i][k + 1]; | |
| V[i][k + 1] = V[i][k]; | |
| V[i][k] = t; | |
| } | |
| } | |
| if (wantu && k < m - 1) { | |
| for (let i = 0; i < m; i++) { | |
| t = U[i][k + 1]; | |
| U[i][k + 1] = U[i][k]; | |
| U[i][k] = t; | |
| } | |
| } | |
| k++; | |
| } | |
| iter = 0; | |
| p--; | |
| break; | |
| } | |
| // no default | |
| } | |
| } | |
| if (swapped) { | |
| var tmp = V; | |
| V = U; | |
| U = tmp; | |
| } | |
| this.m = m; | |
| this.n = n; | |
| this.s = s; | |
| this.U = U; | |
| this.V = V; | |
| } | |
| /** | |
| * Solve a problem of least square (Ax=b) by using the SVD. Useful when A is singular. When A is not singular, it would be better to use qr.solve(value). | |
| * Example : We search to approximate x, with A matrix shape m*n, x vector size n, b vector size m (m > n). We will use : | |
| * var svd = SingularValueDecomposition(A); | |
| * var x = svd.solve(b); | |
| * @param {Matrix} value - Matrix 1D which is the vector b (in the equation Ax = b) | |
| * @return {Matrix} - The vector x | |
| */ | |
| solve(value) { | |
| var Y = value; | |
| var e = this.threshold; | |
| var scols = this.s.length; | |
| var Ls = matrix_Matrix.zeros(scols, scols); | |
| for (let i = 0; i < scols; i++) { | |
| if (Math.abs(this.s[i]) <= e) { | |
| Ls[i][i] = 0; | |
| } else { | |
| Ls[i][i] = 1 / this.s[i]; | |
| } | |
| } | |
| var U = this.U; | |
| var V = this.rightSingularVectors; | |
| var VL = V.mmul(Ls); | |
| var vrows = V.rows; | |
| var urows = U.length; | |
| var VLU = matrix_Matrix.zeros(vrows, urows); | |
| for (let i = 0; i < vrows; i++) { | |
| for (let j = 0; j < urows; j++) { | |
| let sum = 0; | |
| for (let k = 0; k < scols; k++) { | |
| sum += VL[i][k] * U[j][k]; | |
| } | |
| VLU[i][j] = sum; | |
| } | |
| } | |
| return VLU.mmul(Y); | |
| } | |
| /** | |
| * | |
| * @param {Array<number>} value | |
| * @return {Matrix} | |
| */ | |
| solveForDiagonal(value) { | |
| return this.solve(matrix_Matrix.diag(value)); | |
| } | |
| /** | |
| * Get the inverse of the matrix. We compute the inverse of a matrix using SVD when this matrix is singular or ill-conditioned. Example : | |
| * var svd = SingularValueDecomposition(A); | |
| * var inverseA = svd.inverse(); | |
| * @return {Matrix} - The approximation of the inverse of the matrix | |
| */ | |
| inverse() { | |
| var V = this.V; | |
| var e = this.threshold; | |
| var vrows = V.length; | |
| var vcols = V[0].length; | |
| var X = new matrix_Matrix(vrows, this.s.length); | |
| for (let i = 0; i < vrows; i++) { | |
| for (let j = 0; j < vcols; j++) { | |
| if (Math.abs(this.s[j]) > e) { | |
| X[i][j] = V[i][j] / this.s[j]; | |
| } else { | |
| X[i][j] = 0; | |
| } | |
| } | |
| } | |
| var U = this.U; | |
| var urows = U.length; | |
| var ucols = U[0].length; | |
| var Y = new matrix_Matrix(vrows, urows); | |
| for (let i = 0; i < vrows; i++) { | |
| for (let j = 0; j < urows; j++) { | |
| let sum = 0; | |
| for (let k = 0; k < ucols; k++) { | |
| sum += X[i][k] * U[j][k]; | |
| } | |
| Y[i][j] = sum; | |
| } | |
| } | |
| return Y; | |
| } | |
| /** | |
| * | |
| * @return {number} | |
| */ | |
| get condition() { | |
| return this.s[0] / this.s[Math.min(this.m, this.n) - 1]; | |
| } | |
| /** | |
| * | |
| * @return {number} | |
| */ | |
| get norm2() { | |
| return this.s[0]; | |
| } | |
| /** | |
| * | |
| * @return {number} | |
| */ | |
| get rank() { | |
| var tol = Math.max(this.m, this.n) * this.s[0] * Number.EPSILON; | |
| var r = 0; | |
| var s = this.s; | |
| for (var i = 0, ii = s.length; i < ii; i++) { | |
| if (s[i] > tol) { | |
| r++; | |
| } | |
| } | |
| return r; | |
| } | |
| /** | |
| * | |
| * @return {Array<number>} | |
| */ | |
| get diagonal() { | |
| return this.s; | |
| } | |
| /** | |
| * | |
| * @return {number} | |
| */ | |
| get threshold() { | |
| return Number.EPSILON / 2 * Math.max(this.m, this.n) * this.s[0]; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get leftSingularVectors() { | |
| if (!matrix_Matrix.isMatrix(this.U)) { | |
| this.U = new matrix_Matrix(this.U); | |
| } | |
| return this.U; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get rightSingularVectors() { | |
| if (!matrix_Matrix.isMatrix(this.V)) { | |
| this.V = new matrix_Matrix(this.V); | |
| } | |
| return this.V; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get diagonalMatrix() { | |
| return matrix_Matrix.diag(this.s); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/util.js | |
| /** | |
| * @private | |
| * Check that a row index is not out of bounds | |
| * @param {Matrix} matrix | |
| * @param {number} index | |
| * @param {boolean} [outer] | |
| */ | |
| function checkRowIndex(matrix, index, outer) { | |
| var max = outer ? matrix.rows : matrix.rows - 1; | |
| if (index < 0 || index > max) { | |
| throw new RangeError('Row index out of range'); | |
| } | |
| } | |
| /** | |
| * @private | |
| * Check that a column index is not out of bounds | |
| * @param {Matrix} matrix | |
| * @param {number} index | |
| * @param {boolean} [outer] | |
| */ | |
| function checkColumnIndex(matrix, index, outer) { | |
| var max = outer ? matrix.columns : matrix.columns - 1; | |
| if (index < 0 || index > max) { | |
| throw new RangeError('Column index out of range'); | |
| } | |
| } | |
| /** | |
| * @private | |
| * Check that the provided vector is an array with the right length | |
| * @param {Matrix} matrix | |
| * @param {Array|Matrix} vector | |
| * @return {Array} | |
| * @throws {RangeError} | |
| */ | |
| function checkRowVector(matrix, vector) { | |
| if (vector.to1DArray) { | |
| vector = vector.to1DArray(); | |
| } | |
| if (vector.length !== matrix.columns) { | |
| throw new RangeError( | |
| 'vector size must be the same as the number of columns' | |
| ); | |
| } | |
| return vector; | |
| } | |
| /** | |
| * @private | |
| * Check that the provided vector is an array with the right length | |
| * @param {Matrix} matrix | |
| * @param {Array|Matrix} vector | |
| * @return {Array} | |
| * @throws {RangeError} | |
| */ | |
| function checkColumnVector(matrix, vector) { | |
| if (vector.to1DArray) { | |
| vector = vector.to1DArray(); | |
| } | |
| if (vector.length !== matrix.rows) { | |
| throw new RangeError('vector size must be the same as the number of rows'); | |
| } | |
| return vector; | |
| } | |
| function checkIndices(matrix, rowIndices, columnIndices) { | |
| return { | |
| row: checkRowIndices(matrix, rowIndices), | |
| column: checkColumnIndices(matrix, columnIndices) | |
| }; | |
| } | |
| function checkRowIndices(matrix, rowIndices) { | |
| if (typeof rowIndices !== 'object') { | |
| throw new TypeError('unexpected type for row indices'); | |
| } | |
| var rowOut = rowIndices.some((r) => { | |
| return r < 0 || r >= matrix.rows; | |
| }); | |
| if (rowOut) { | |
| throw new RangeError('row indices are out of range'); | |
| } | |
| if (!Array.isArray(rowIndices)) rowIndices = Array.from(rowIndices); | |
| return rowIndices; | |
| } | |
| function checkColumnIndices(matrix, columnIndices) { | |
| if (typeof columnIndices !== 'object') { | |
| throw new TypeError('unexpected type for column indices'); | |
| } | |
| var columnOut = columnIndices.some((c) => { | |
| return c < 0 || c >= matrix.columns; | |
| }); | |
| if (columnOut) { | |
| throw new RangeError('column indices are out of range'); | |
| } | |
| if (!Array.isArray(columnIndices)) columnIndices = Array.from(columnIndices); | |
| return columnIndices; | |
| } | |
| function checkRange(matrix, startRow, endRow, startColumn, endColumn) { | |
| if (arguments.length !== 5) { | |
| throw new RangeError('expected 4 arguments'); | |
| } | |
| checkNumber('startRow', startRow); | |
| checkNumber('endRow', endRow); | |
| checkNumber('startColumn', startColumn); | |
| checkNumber('endColumn', endColumn); | |
| if ( | |
| startRow > endRow || | |
| startColumn > endColumn || | |
| startRow < 0 || | |
| startRow >= matrix.rows || | |
| endRow < 0 || | |
| endRow >= matrix.rows || | |
| startColumn < 0 || | |
| startColumn >= matrix.columns || | |
| endColumn < 0 || | |
| endColumn >= matrix.columns | |
| ) { | |
| throw new RangeError('Submatrix indices are out of range'); | |
| } | |
| } | |
| function getRange(from, to) { | |
| var arr = new Array(to - from + 1); | |
| for (var i = 0; i < arr.length; i++) { | |
| arr[i] = from + i; | |
| } | |
| return arr; | |
| } | |
| function sumByRow(matrix) { | |
| var sum = matrix_Matrix.zeros(matrix.rows, 1); | |
| for (var i = 0; i < matrix.rows; ++i) { | |
| for (var j = 0; j < matrix.columns; ++j) { | |
| sum.set(i, 0, sum.get(i, 0) + matrix.get(i, j)); | |
| } | |
| } | |
| return sum; | |
| } | |
| function sumByColumn(matrix) { | |
| var sum = matrix_Matrix.zeros(1, matrix.columns); | |
| for (var i = 0; i < matrix.rows; ++i) { | |
| for (var j = 0; j < matrix.columns; ++j) { | |
| sum.set(0, j, sum.get(0, j) + matrix.get(i, j)); | |
| } | |
| } | |
| return sum; | |
| } | |
| function sumAll(matrix) { | |
| var v = 0; | |
| for (var i = 0; i < matrix.rows; i++) { | |
| for (var j = 0; j < matrix.columns; j++) { | |
| v += matrix.get(i, j); | |
| } | |
| } | |
| return v; | |
| } | |
| function checkNumber(name, value) { | |
| if (typeof value !== 'number') { | |
| throw new TypeError(`${name} must be a number`); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/base.js | |
| class base_BaseView extends AbstractMatrix() { | |
| constructor(matrix, rows, columns) { | |
| super(); | |
| this.matrix = matrix; | |
| this.rows = rows; | |
| this.columns = columns; | |
| } | |
| static get [Symbol.species]() { | |
| return matrix_Matrix; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/transpose.js | |
| class transpose_MatrixTransposeView extends base_BaseView { | |
| constructor(matrix) { | |
| super(matrix, matrix.columns, matrix.rows); | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(columnIndex, rowIndex, value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(columnIndex, rowIndex); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/row.js | |
| class row_MatrixRowView extends base_BaseView { | |
| constructor(matrix, row) { | |
| super(matrix, 1, matrix.columns); | |
| this.row = row; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(this.row, columnIndex, value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(this.row, columnIndex); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/sub.js | |
| class sub_MatrixSubView extends base_BaseView { | |
| constructor(matrix, startRow, endRow, startColumn, endColumn) { | |
| checkRange(matrix, startRow, endRow, startColumn, endColumn); | |
| super(matrix, endRow - startRow + 1, endColumn - startColumn + 1); | |
| this.startRow = startRow; | |
| this.startColumn = startColumn; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set( | |
| this.startRow + rowIndex, | |
| this.startColumn + columnIndex, | |
| value | |
| ); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get( | |
| this.startRow + rowIndex, | |
| this.startColumn + columnIndex | |
| ); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/selection.js | |
| class selection_MatrixSelectionView extends base_BaseView { | |
| constructor(matrix, rowIndices, columnIndices) { | |
| var indices = checkIndices(matrix, rowIndices, columnIndices); | |
| super(matrix, indices.row.length, indices.column.length); | |
| this.rowIndices = indices.row; | |
| this.columnIndices = indices.column; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set( | |
| this.rowIndices[rowIndex], | |
| this.columnIndices[columnIndex], | |
| value | |
| ); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get( | |
| this.rowIndices[rowIndex], | |
| this.columnIndices[columnIndex] | |
| ); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/rowSelection.js | |
| class rowSelection_MatrixRowSelectionView extends base_BaseView { | |
| constructor(matrix, rowIndices) { | |
| rowIndices = checkRowIndices(matrix, rowIndices); | |
| super(matrix, rowIndices.length, matrix.columns); | |
| this.rowIndices = rowIndices; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(this.rowIndices[rowIndex], columnIndex, value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(this.rowIndices[rowIndex], columnIndex); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/columnSelection.js | |
| class columnSelection_MatrixColumnSelectionView extends base_BaseView { | |
| constructor(matrix, columnIndices) { | |
| columnIndices = checkColumnIndices(matrix, columnIndices); | |
| super(matrix, matrix.rows, columnIndices.length); | |
| this.columnIndices = columnIndices; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(rowIndex, this.columnIndices[columnIndex], value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(rowIndex, this.columnIndices[columnIndex]); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/column.js | |
| class column_MatrixColumnView extends base_BaseView { | |
| constructor(matrix, column) { | |
| super(matrix, matrix.rows, 1); | |
| this.column = column; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(rowIndex, this.column, value); | |
| return this; | |
| } | |
| get(rowIndex) { | |
| return this.matrix.get(rowIndex, this.column); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/flipRow.js | |
| class flipRow_MatrixFlipRowView extends base_BaseView { | |
| constructor(matrix) { | |
| super(matrix, matrix.rows, matrix.columns); | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(this.rows - rowIndex - 1, columnIndex, value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(this.rows - rowIndex - 1, columnIndex); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/views/flipColumn.js | |
| class flipColumn_MatrixFlipColumnView extends base_BaseView { | |
| constructor(matrix) { | |
| super(matrix, matrix.rows, matrix.columns); | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.matrix.set(rowIndex, this.columns - columnIndex - 1, value); | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.matrix.get(rowIndex, this.columns - columnIndex - 1); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/abstractMatrix.js | |
| function AbstractMatrix(superCtor) { | |
| if (superCtor === undefined) superCtor = Object; | |
| /** | |
| * Real matrix | |
| * @class Matrix | |
| * @param {number|Array|Matrix} nRows - Number of rows of the new matrix, | |
| * 2D array containing the data or Matrix instance to clone | |
| * @param {number} [nColumns] - Number of columns of the new matrix | |
| */ | |
| class Matrix extends superCtor { | |
| static get [Symbol.species]() { | |
| return this; | |
| } | |
| /** | |
| * Constructs a Matrix with the chosen dimensions from a 1D array | |
| * @param {number} newRows - Number of rows | |
| * @param {number} newColumns - Number of columns | |
| * @param {Array} newData - A 1D array containing data for the matrix | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static from1DArray(newRows, newColumns, newData) { | |
| var length = newRows * newColumns; | |
| if (length !== newData.length) { | |
| throw new RangeError('Data length does not match given dimensions'); | |
| } | |
| var newMatrix = new this(newRows, newColumns); | |
| for (var row = 0; row < newRows; row++) { | |
| for (var column = 0; column < newColumns; column++) { | |
| newMatrix.set(row, column, newData[row * newColumns + column]); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Creates a row vector, a matrix with only one row. | |
| * @param {Array} newData - A 1D array containing data for the vector | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static rowVector(newData) { | |
| var vector = new this(1, newData.length); | |
| for (var i = 0; i < newData.length; i++) { | |
| vector.set(0, i, newData[i]); | |
| } | |
| return vector; | |
| } | |
| /** | |
| * Creates a column vector, a matrix with only one column. | |
| * @param {Array} newData - A 1D array containing data for the vector | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static columnVector(newData) { | |
| var vector = new this(newData.length, 1); | |
| for (var i = 0; i < newData.length; i++) { | |
| vector.set(i, 0, newData[i]); | |
| } | |
| return vector; | |
| } | |
| /** | |
| * Creates an empty matrix with the given dimensions. Values will be undefined. Same as using new Matrix(rows, columns). | |
| * @param {number} rows - Number of rows | |
| * @param {number} columns - Number of columns | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static empty(rows, columns) { | |
| return new this(rows, columns); | |
| } | |
| /** | |
| * Creates a matrix with the given dimensions. Values will be set to zero. | |
| * @param {number} rows - Number of rows | |
| * @param {number} columns - Number of columns | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static zeros(rows, columns) { | |
| return this.empty(rows, columns).fill(0); | |
| } | |
| /** | |
| * Creates a matrix with the given dimensions. Values will be set to one. | |
| * @param {number} rows - Number of rows | |
| * @param {number} columns - Number of columns | |
| * @return {Matrix} - The new matrix | |
| */ | |
| static ones(rows, columns) { | |
| return this.empty(rows, columns).fill(1); | |
| } | |
| /** | |
| * Creates a matrix with the given dimensions. Values will be randomly set. | |
| * @param {number} rows - Number of rows | |
| * @param {number} columns - Number of columns | |
| * @param {function} [rng=Math.random] - Random number generator | |
| * @return {Matrix} The new matrix | |
| */ | |
| static rand(rows, columns, rng) { | |
| if (rng === undefined) rng = Math.random; | |
| var matrix = this.empty(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| matrix.set(i, j, rng()); | |
| } | |
| } | |
| return matrix; | |
| } | |
| /** | |
| * Creates a matrix with the given dimensions. Values will be random integers. | |
| * @param {number} rows - Number of rows | |
| * @param {number} columns - Number of columns | |
| * @param {number} [maxValue=1000] - Maximum value | |
| * @param {function} [rng=Math.random] - Random number generator | |
| * @return {Matrix} The new matrix | |
| */ | |
| static randInt(rows, columns, maxValue, rng) { | |
| if (maxValue === undefined) maxValue = 1000; | |
| if (rng === undefined) rng = Math.random; | |
| var matrix = this.empty(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| var value = Math.floor(rng() * maxValue); | |
| matrix.set(i, j, value); | |
| } | |
| } | |
| return matrix; | |
| } | |
| /** | |
| * Creates an identity matrix with the given dimension. Values of the diagonal will be 1 and others will be 0. | |
| * @param {number} rows - Number of rows | |
| * @param {number} [columns=rows] - Number of columns | |
| * @param {number} [value=1] - Value to fill the diagonal with | |
| * @return {Matrix} - The new identity matrix | |
| */ | |
| static eye(rows, columns, value) { | |
| if (columns === undefined) columns = rows; | |
| if (value === undefined) value = 1; | |
| var min = Math.min(rows, columns); | |
| var matrix = this.zeros(rows, columns); | |
| for (var i = 0; i < min; i++) { | |
| matrix.set(i, i, value); | |
| } | |
| return matrix; | |
| } | |
| /** | |
| * Creates a diagonal matrix based on the given array. | |
| * @param {Array} data - Array containing the data for the diagonal | |
| * @param {number} [rows] - Number of rows (Default: data.length) | |
| * @param {number} [columns] - Number of columns (Default: rows) | |
| * @return {Matrix} - The new diagonal matrix | |
| */ | |
| static diag(data, rows, columns) { | |
| var l = data.length; | |
| if (rows === undefined) rows = l; | |
| if (columns === undefined) columns = rows; | |
| var min = Math.min(l, rows, columns); | |
| var matrix = this.zeros(rows, columns); | |
| for (var i = 0; i < min; i++) { | |
| matrix.set(i, i, data[i]); | |
| } | |
| return matrix; | |
| } | |
| /** | |
| * Returns a matrix whose elements are the minimum between matrix1 and matrix2 | |
| * @param {Matrix} matrix1 | |
| * @param {Matrix} matrix2 | |
| * @return {Matrix} | |
| */ | |
| static min(matrix1, matrix2) { | |
| matrix1 = this.checkMatrix(matrix1); | |
| matrix2 = this.checkMatrix(matrix2); | |
| var rows = matrix1.rows; | |
| var columns = matrix1.columns; | |
| var result = new this(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j))); | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Returns a matrix whose elements are the maximum between matrix1 and matrix2 | |
| * @param {Matrix} matrix1 | |
| * @param {Matrix} matrix2 | |
| * @return {Matrix} | |
| */ | |
| static max(matrix1, matrix2) { | |
| matrix1 = this.checkMatrix(matrix1); | |
| matrix2 = this.checkMatrix(matrix2); | |
| var rows = matrix1.rows; | |
| var columns = matrix1.columns; | |
| var result = new this(rows, columns); | |
| for (var i = 0; i < rows; i++) { | |
| for (var j = 0; j < columns; j++) { | |
| result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j))); | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Check that the provided value is a Matrix and tries to instantiate one if not | |
| * @param {*} value - The value to check | |
| * @return {Matrix} | |
| */ | |
| static checkMatrix(value) { | |
| return Matrix.isMatrix(value) ? value : new this(value); | |
| } | |
| /** | |
| * Returns true if the argument is a Matrix, false otherwise | |
| * @param {*} value - The value to check | |
| * @return {boolean} | |
| */ | |
| static isMatrix(value) { | |
| return (value != null) && (value.klass === 'Matrix'); | |
| } | |
| /** | |
| * @prop {number} size - The number of elements in the matrix. | |
| */ | |
| get size() { | |
| return this.rows * this.columns; | |
| } | |
| /** | |
| * Applies a callback for each element of the matrix. The function is called in the matrix (this) context. | |
| * @param {function} callback - Function that will be called with two parameters : i (row) and j (column) | |
| * @return {Matrix} this | |
| */ | |
| apply(callback) { | |
| if (typeof callback !== 'function') { | |
| throw new TypeError('callback must be a function'); | |
| } | |
| var ii = this.rows; | |
| var jj = this.columns; | |
| for (var i = 0; i < ii; i++) { | |
| for (var j = 0; j < jj; j++) { | |
| callback.call(this, i, j); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Returns a new 1D array filled row by row with the matrix values | |
| * @return {Array} | |
| */ | |
| to1DArray() { | |
| var array = new Array(this.size); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| array[i * this.columns + j] = this.get(i, j); | |
| } | |
| } | |
| return array; | |
| } | |
| /** | |
| * Returns a 2D array containing a copy of the data | |
| * @return {Array} | |
| */ | |
| to2DArray() { | |
| var copy = new Array(this.rows); | |
| for (var i = 0; i < this.rows; i++) { | |
| copy[i] = new Array(this.columns); | |
| for (var j = 0; j < this.columns; j++) { | |
| copy[i][j] = this.get(i, j); | |
| } | |
| } | |
| return copy; | |
| } | |
| /** | |
| * @return {boolean} true if the matrix has one row | |
| */ | |
| isRowVector() { | |
| return this.rows === 1; | |
| } | |
| /** | |
| * @return {boolean} true if the matrix has one column | |
| */ | |
| isColumnVector() { | |
| return this.columns === 1; | |
| } | |
| /** | |
| * @return {boolean} true if the matrix has one row or one column | |
| */ | |
| isVector() { | |
| return (this.rows === 1) || (this.columns === 1); | |
| } | |
| /** | |
| * @return {boolean} true if the matrix has the same number of rows and columns | |
| */ | |
| isSquare() { | |
| return this.rows === this.columns; | |
| } | |
| /** | |
| * @return {boolean} true if the matrix is square and has the same values on both sides of the diagonal | |
| */ | |
| isSymmetric() { | |
| if (this.isSquare()) { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j <= i; j++) { | |
| if (this.get(i, j) !== this.get(j, i)) { | |
| return false; | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| return false; | |
| } | |
| /** | |
| * Sets a given element of the matrix. mat.set(3,4,1) is equivalent to mat[3][4]=1 | |
| * @abstract | |
| * @param {number} rowIndex - Index of the row | |
| * @param {number} columnIndex - Index of the column | |
| * @param {number} value - The new value for the element | |
| * @return {Matrix} this | |
| */ | |
| set(rowIndex, columnIndex, value) { // eslint-disable-line no-unused-vars | |
| throw new Error('set method is unimplemented'); | |
| } | |
| /** | |
| * Returns the given element of the matrix. mat.get(3,4) is equivalent to matrix[3][4] | |
| * @abstract | |
| * @param {number} rowIndex - Index of the row | |
| * @param {number} columnIndex - Index of the column | |
| * @return {number} | |
| */ | |
| get(rowIndex, columnIndex) { // eslint-disable-line no-unused-vars | |
| throw new Error('get method is unimplemented'); | |
| } | |
| /** | |
| * Creates a new matrix that is a repetition of the current matrix. New matrix has rowRep times the number of | |
| * rows of the matrix, and colRep times the number of columns of the matrix | |
| * @param {number} rowRep - Number of times the rows should be repeated | |
| * @param {number} colRep - Number of times the columns should be re | |
| * @return {Matrix} | |
| * @example | |
| * var matrix = new Matrix([[1,2]]); | |
| * matrix.repeat(2); // [[1,2],[1,2]] | |
| */ | |
| repeat(rowRep, colRep) { | |
| rowRep = rowRep || 1; | |
| colRep = colRep || 1; | |
| var matrix = new this.constructor[Symbol.species](this.rows * rowRep, this.columns * colRep); | |
| for (var i = 0; i < rowRep; i++) { | |
| for (var j = 0; j < colRep; j++) { | |
| matrix.setSubMatrix(this, this.rows * i, this.columns * j); | |
| } | |
| } | |
| return matrix; | |
| } | |
| /** | |
| * Fills the matrix with a given value. All elements will be set to this value. | |
| * @param {number} value - New value | |
| * @return {Matrix} this | |
| */ | |
| fill(value) { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, value); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Negates the matrix. All elements will be multiplied by (-1) | |
| * @return {Matrix} this | |
| */ | |
| neg() { | |
| return this.mulS(-1); | |
| } | |
| /** | |
| * Returns a new array from the given row index | |
| * @param {number} index - Row index | |
| * @return {Array} | |
| */ | |
| getRow(index) { | |
| checkRowIndex(this, index); | |
| var row = new Array(this.columns); | |
| for (var i = 0; i < this.columns; i++) { | |
| row[i] = this.get(index, i); | |
| } | |
| return row; | |
| } | |
| /** | |
| * Returns a new row vector from the given row index | |
| * @param {number} index - Row index | |
| * @return {Matrix} | |
| */ | |
| getRowVector(index) { | |
| return this.constructor.rowVector(this.getRow(index)); | |
| } | |
| /** | |
| * Sets a row at the given index | |
| * @param {number} index - Row index | |
| * @param {Array|Matrix} array - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| setRow(index, array) { | |
| checkRowIndex(this, index); | |
| array = checkRowVector(this, array); | |
| for (var i = 0; i < this.columns; i++) { | |
| this.set(index, i, array[i]); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Swaps two rows | |
| * @param {number} row1 - First row index | |
| * @param {number} row2 - Second row index | |
| * @return {Matrix} this | |
| */ | |
| swapRows(row1, row2) { | |
| checkRowIndex(this, row1); | |
| checkRowIndex(this, row2); | |
| for (var i = 0; i < this.columns; i++) { | |
| var temp = this.get(row1, i); | |
| this.set(row1, i, this.get(row2, i)); | |
| this.set(row2, i, temp); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Returns a new array from the given column index | |
| * @param {number} index - Column index | |
| * @return {Array} | |
| */ | |
| getColumn(index) { | |
| checkColumnIndex(this, index); | |
| var column = new Array(this.rows); | |
| for (var i = 0; i < this.rows; i++) { | |
| column[i] = this.get(i, index); | |
| } | |
| return column; | |
| } | |
| /** | |
| * Returns a new column vector from the given column index | |
| * @param {number} index - Column index | |
| * @return {Matrix} | |
| */ | |
| getColumnVector(index) { | |
| return this.constructor.columnVector(this.getColumn(index)); | |
| } | |
| /** | |
| * Sets a column at the given index | |
| * @param {number} index - Column index | |
| * @param {Array|Matrix} array - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| setColumn(index, array) { | |
| checkColumnIndex(this, index); | |
| array = checkColumnVector(this, array); | |
| for (var i = 0; i < this.rows; i++) { | |
| this.set(i, index, array[i]); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Swaps two columns | |
| * @param {number} column1 - First column index | |
| * @param {number} column2 - Second column index | |
| * @return {Matrix} this | |
| */ | |
| swapColumns(column1, column2) { | |
| checkColumnIndex(this, column1); | |
| checkColumnIndex(this, column2); | |
| for (var i = 0; i < this.rows; i++) { | |
| var temp = this.get(i, column1); | |
| this.set(i, column1, this.get(i, column2)); | |
| this.set(i, column2, temp); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Adds the values of a vector to each row | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| addRowVector(vector) { | |
| vector = checkRowVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) + vector[j]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Subtracts the values of a vector from each row | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| subRowVector(vector) { | |
| vector = checkRowVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) - vector[j]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Multiplies the values of a vector with each row | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| mulRowVector(vector) { | |
| vector = checkRowVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) * vector[j]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Divides the values of each row by those of a vector | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| divRowVector(vector) { | |
| vector = checkRowVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) / vector[j]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Adds the values of a vector to each column | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| addColumnVector(vector) { | |
| vector = checkColumnVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) + vector[i]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Subtracts the values of a vector from each column | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| subColumnVector(vector) { | |
| vector = checkColumnVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) - vector[i]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Multiplies the values of a vector with each column | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| mulColumnVector(vector) { | |
| vector = checkColumnVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) * vector[i]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Divides the values of each column by those of a vector | |
| * @param {Array|Matrix} vector - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| divColumnVector(vector) { | |
| vector = checkColumnVector(this, vector); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) / vector[i]); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Multiplies the values of a row with a scalar | |
| * @param {number} index - Row index | |
| * @param {number} value | |
| * @return {Matrix} this | |
| */ | |
| mulRow(index, value) { | |
| checkRowIndex(this, index); | |
| for (var i = 0; i < this.columns; i++) { | |
| this.set(index, i, this.get(index, i) * value); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Multiplies the values of a column with a scalar | |
| * @param {number} index - Column index | |
| * @param {number} value | |
| * @return {Matrix} this | |
| */ | |
| mulColumn(index, value) { | |
| checkColumnIndex(this, index); | |
| for (var i = 0; i < this.rows; i++) { | |
| this.set(i, index, this.get(i, index) * value); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Returns the maximum value of the matrix | |
| * @return {number} | |
| */ | |
| max() { | |
| var v = this.get(0, 0); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| if (this.get(i, j) > v) { | |
| v = this.get(i, j); | |
| } | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the maximum value | |
| * @return {Array} | |
| */ | |
| maxIndex() { | |
| var v = this.get(0, 0); | |
| var idx = [0, 0]; | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| if (this.get(i, j) > v) { | |
| v = this.get(i, j); | |
| idx[0] = i; | |
| idx[1] = j; | |
| } | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns the minimum value of the matrix | |
| * @return {number} | |
| */ | |
| min() { | |
| var v = this.get(0, 0); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| if (this.get(i, j) < v) { | |
| v = this.get(i, j); | |
| } | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the minimum value | |
| * @return {Array} | |
| */ | |
| minIndex() { | |
| var v = this.get(0, 0); | |
| var idx = [0, 0]; | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| if (this.get(i, j) < v) { | |
| v = this.get(i, j); | |
| idx[0] = i; | |
| idx[1] = j; | |
| } | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns the maximum value of one row | |
| * @param {number} row - Row index | |
| * @return {number} | |
| */ | |
| maxRow(row) { | |
| checkRowIndex(this, row); | |
| var v = this.get(row, 0); | |
| for (var i = 1; i < this.columns; i++) { | |
| if (this.get(row, i) > v) { | |
| v = this.get(row, i); | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the maximum value of one row | |
| * @param {number} row - Row index | |
| * @return {Array} | |
| */ | |
| maxRowIndex(row) { | |
| checkRowIndex(this, row); | |
| var v = this.get(row, 0); | |
| var idx = [row, 0]; | |
| for (var i = 1; i < this.columns; i++) { | |
| if (this.get(row, i) > v) { | |
| v = this.get(row, i); | |
| idx[1] = i; | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns the minimum value of one row | |
| * @param {number} row - Row index | |
| * @return {number} | |
| */ | |
| minRow(row) { | |
| checkRowIndex(this, row); | |
| var v = this.get(row, 0); | |
| for (var i = 1; i < this.columns; i++) { | |
| if (this.get(row, i) < v) { | |
| v = this.get(row, i); | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the maximum value of one row | |
| * @param {number} row - Row index | |
| * @return {Array} | |
| */ | |
| minRowIndex(row) { | |
| checkRowIndex(this, row); | |
| var v = this.get(row, 0); | |
| var idx = [row, 0]; | |
| for (var i = 1; i < this.columns; i++) { | |
| if (this.get(row, i) < v) { | |
| v = this.get(row, i); | |
| idx[1] = i; | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns the maximum value of one column | |
| * @param {number} column - Column index | |
| * @return {number} | |
| */ | |
| maxColumn(column) { | |
| checkColumnIndex(this, column); | |
| var v = this.get(0, column); | |
| for (var i = 1; i < this.rows; i++) { | |
| if (this.get(i, column) > v) { | |
| v = this.get(i, column); | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the maximum value of one column | |
| * @param {number} column - Column index | |
| * @return {Array} | |
| */ | |
| maxColumnIndex(column) { | |
| checkColumnIndex(this, column); | |
| var v = this.get(0, column); | |
| var idx = [0, column]; | |
| for (var i = 1; i < this.rows; i++) { | |
| if (this.get(i, column) > v) { | |
| v = this.get(i, column); | |
| idx[0] = i; | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns the minimum value of one column | |
| * @param {number} column - Column index | |
| * @return {number} | |
| */ | |
| minColumn(column) { | |
| checkColumnIndex(this, column); | |
| var v = this.get(0, column); | |
| for (var i = 1; i < this.rows; i++) { | |
| if (this.get(i, column) < v) { | |
| v = this.get(i, column); | |
| } | |
| } | |
| return v; | |
| } | |
| /** | |
| * Returns the index of the minimum value of one column | |
| * @param {number} column - Column index | |
| * @return {Array} | |
| */ | |
| minColumnIndex(column) { | |
| checkColumnIndex(this, column); | |
| var v = this.get(0, column); | |
| var idx = [0, column]; | |
| for (var i = 1; i < this.rows; i++) { | |
| if (this.get(i, column) < v) { | |
| v = this.get(i, column); | |
| idx[0] = i; | |
| } | |
| } | |
| return idx; | |
| } | |
| /** | |
| * Returns an array containing the diagonal values of the matrix | |
| * @return {Array} | |
| */ | |
| diag() { | |
| var min = Math.min(this.rows, this.columns); | |
| var diag = new Array(min); | |
| for (var i = 0; i < min; i++) { | |
| diag[i] = this.get(i, i); | |
| } | |
| return diag; | |
| } | |
| /** | |
| * Returns the sum by the argument given, if no argument given, | |
| * it returns the sum of all elements of the matrix. | |
| * @param {string} by - sum by 'row' or 'column'. | |
| * @return {Matrix|number} | |
| */ | |
| sum(by) { | |
| switch (by) { | |
| case 'row': | |
| return sumByRow(this); | |
| case 'column': | |
| return sumByColumn(this); | |
| default: | |
| return sumAll(this); | |
| } | |
| } | |
| /** | |
| * Returns the mean of all elements of the matrix | |
| * @return {number} | |
| */ | |
| mean() { | |
| return this.sum() / this.size; | |
| } | |
| /** | |
| * Returns the product of all elements of the matrix | |
| * @return {number} | |
| */ | |
| prod() { | |
| var prod = 1; | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| prod *= this.get(i, j); | |
| } | |
| } | |
| return prod; | |
| } | |
| /** | |
| * Returns the norm of a matrix. | |
| * @param {string} type - "frobenius" (default) or "max" return resp. the Frobenius norm and the max norm. | |
| * @return {number} | |
| */ | |
| norm(type = 'frobenius') { | |
| var result = 0; | |
| if (type === 'max') { | |
| return this.max(); | |
| } else if (type === 'frobenius') { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| result = result + this.get(i, j) * this.get(i, j); | |
| } | |
| } | |
| return Math.sqrt(result); | |
| } else { | |
| throw new RangeError(`unknown norm type: ${type}`); | |
| } | |
| } | |
| /** | |
| * Computes the cumulative sum of the matrix elements (in place, row by row) | |
| * @return {Matrix} this | |
| */ | |
| cumulativeSum() { | |
| var sum = 0; | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| sum += this.get(i, j); | |
| this.set(i, j, sum); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Computes the dot (scalar) product between the matrix and another | |
| * @param {Matrix} vector2 vector | |
| * @return {number} | |
| */ | |
| dot(vector2) { | |
| if (Matrix.isMatrix(vector2)) vector2 = vector2.to1DArray(); | |
| var vector1 = this.to1DArray(); | |
| if (vector1.length !== vector2.length) { | |
| throw new RangeError('vectors do not have the same size'); | |
| } | |
| var dot = 0; | |
| for (var i = 0; i < vector1.length; i++) { | |
| dot += vector1[i] * vector2[i]; | |
| } | |
| return dot; | |
| } | |
| /** | |
| * Returns the matrix product between this and other | |
| * @param {Matrix} other | |
| * @return {Matrix} | |
| */ | |
| mmul(other) { | |
| other = this.constructor.checkMatrix(other); | |
| if (this.columns !== other.rows) { | |
| // eslint-disable-next-line no-console | |
| console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); | |
| } | |
| var m = this.rows; | |
| var n = this.columns; | |
| var p = other.columns; | |
| var result = new this.constructor[Symbol.species](m, p); | |
| var Bcolj = new Array(n); | |
| for (var j = 0; j < p; j++) { | |
| for (var k = 0; k < n; k++) { | |
| Bcolj[k] = other.get(k, j); | |
| } | |
| for (var i = 0; i < m; i++) { | |
| var s = 0; | |
| for (k = 0; k < n; k++) { | |
| s += this.get(i, k) * Bcolj[k]; | |
| } | |
| result.set(i, j, s); | |
| } | |
| } | |
| return result; | |
| } | |
| strassen2x2(other) { | |
| var result = new this.constructor[Symbol.species](2, 2); | |
| const a11 = this.get(0, 0); | |
| const b11 = other.get(0, 0); | |
| const a12 = this.get(0, 1); | |
| const b12 = other.get(0, 1); | |
| const a21 = this.get(1, 0); | |
| const b21 = other.get(1, 0); | |
| const a22 = this.get(1, 1); | |
| const b22 = other.get(1, 1); | |
| // Compute intermediate values. | |
| const m1 = (a11 + a22) * (b11 + b22); | |
| const m2 = (a21 + a22) * b11; | |
| const m3 = a11 * (b12 - b22); | |
| const m4 = a22 * (b21 - b11); | |
| const m5 = (a11 + a12) * b22; | |
| const m6 = (a21 - a11) * (b11 + b12); | |
| const m7 = (a12 - a22) * (b21 + b22); | |
| // Combine intermediate values into the output. | |
| const c00 = m1 + m4 - m5 + m7; | |
| const c01 = m3 + m5; | |
| const c10 = m2 + m4; | |
| const c11 = m1 - m2 + m3 + m6; | |
| result.set(0, 0, c00); | |
| result.set(0, 1, c01); | |
| result.set(1, 0, c10); | |
| result.set(1, 1, c11); | |
| return result; | |
| } | |
| strassen3x3(other) { | |
| var result = new this.constructor[Symbol.species](3, 3); | |
| const a00 = this.get(0, 0); | |
| const a01 = this.get(0, 1); | |
| const a02 = this.get(0, 2); | |
| const a10 = this.get(1, 0); | |
| const a11 = this.get(1, 1); | |
| const a12 = this.get(1, 2); | |
| const a20 = this.get(2, 0); | |
| const a21 = this.get(2, 1); | |
| const a22 = this.get(2, 2); | |
| const b00 = other.get(0, 0); | |
| const b01 = other.get(0, 1); | |
| const b02 = other.get(0, 2); | |
| const b10 = other.get(1, 0); | |
| const b11 = other.get(1, 1); | |
| const b12 = other.get(1, 2); | |
| const b20 = other.get(2, 0); | |
| const b21 = other.get(2, 1); | |
| const b22 = other.get(2, 2); | |
| const m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11; | |
| const m2 = (a00 - a10) * (-b01 + b11); | |
| const m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22); | |
| const m4 = (-a00 + a10 + a11) * (b00 - b01 + b11); | |
| const m5 = (a10 + a11) * (-b00 + b01); | |
| const m6 = a00 * b00; | |
| const m7 = (-a00 + a20 + a21) * (b00 - b02 + b12); | |
| const m8 = (-a00 + a20) * (b02 - b12); | |
| const m9 = (a20 + a21) * (-b00 + b02); | |
| const m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12; | |
| const m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21); | |
| const m12 = (-a02 + a21 + a22) * (b11 + b20 - b21); | |
| const m13 = (a02 - a22) * (b11 - b21); | |
| const m14 = a02 * b20; | |
| const m15 = (a21 + a22) * (-b20 + b21); | |
| const m16 = (-a02 + a11 + a12) * (b12 + b20 - b22); | |
| const m17 = (a02 - a12) * (b12 - b22); | |
| const m18 = (a11 + a12) * (-b20 + b22); | |
| const m19 = a01 * b10; | |
| const m20 = a12 * b21; | |
| const m21 = a10 * b02; | |
| const m22 = a20 * b01; | |
| const m23 = a22 * b22; | |
| const c00 = m6 + m14 + m19; | |
| const c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15; | |
| const c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18; | |
| const c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17; | |
| const c11 = m2 + m4 + m5 + m6 + m20; | |
| const c12 = m14 + m16 + m17 + m18 + m21; | |
| const c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14; | |
| const c21 = m12 + m13 + m14 + m15 + m22; | |
| const c22 = m6 + m7 + m8 + m9 + m23; | |
| result.set(0, 0, c00); | |
| result.set(0, 1, c01); | |
| result.set(0, 2, c02); | |
| result.set(1, 0, c10); | |
| result.set(1, 1, c11); | |
| result.set(1, 2, c12); | |
| result.set(2, 0, c20); | |
| result.set(2, 1, c21); | |
| result.set(2, 2, c22); | |
| return result; | |
| } | |
| /** | |
| * Returns the matrix product between x and y. More efficient than mmul(other) only when we multiply squared matrix and when the size of the matrix is > 1000. | |
| * @param {Matrix} y | |
| * @return {Matrix} | |
| */ | |
| mmulStrassen(y) { | |
| var x = this.clone(); | |
| var r1 = x.rows; | |
| var c1 = x.columns; | |
| var r2 = y.rows; | |
| var c2 = y.columns; | |
| if (c1 !== r2) { | |
| // eslint-disable-next-line no-console | |
| console.warn(`Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.`); | |
| } | |
| // Put a matrix into the top left of a matrix of zeros. | |
| // `rows` and `cols` are the dimensions of the output matrix. | |
| function embed(mat, rows, cols) { | |
| var r = mat.rows; | |
| var c = mat.columns; | |
| if ((r === rows) && (c === cols)) { | |
| return mat; | |
| } else { | |
| var resultat = Matrix.zeros(rows, cols); | |
| resultat = resultat.setSubMatrix(mat, 0, 0); | |
| return resultat; | |
| } | |
| } | |
| // Make sure both matrices are the same size. | |
| // This is exclusively for simplicity: | |
| // this algorithm can be implemented with matrices of different sizes. | |
| var r = Math.max(r1, r2); | |
| var c = Math.max(c1, c2); | |
| x = embed(x, r, c); | |
| y = embed(y, r, c); | |
| // Our recursive multiplication function. | |
| function blockMult(a, b, rows, cols) { | |
| // For small matrices, resort to naive multiplication. | |
| if (rows <= 512 || cols <= 512) { | |
| return a.mmul(b); // a is equivalent to this | |
| } | |
| // Apply dynamic padding. | |
| if ((rows % 2 === 1) && (cols % 2 === 1)) { | |
| a = embed(a, rows + 1, cols + 1); | |
| b = embed(b, rows + 1, cols + 1); | |
| } else if (rows % 2 === 1) { | |
| a = embed(a, rows + 1, cols); | |
| b = embed(b, rows + 1, cols); | |
| } else if (cols % 2 === 1) { | |
| a = embed(a, rows, cols + 1); | |
| b = embed(b, rows, cols + 1); | |
| } | |
| var halfRows = parseInt(a.rows / 2, 10); | |
| var halfCols = parseInt(a.columns / 2, 10); | |
| // Subdivide input matrices. | |
| var a11 = a.subMatrix(0, halfRows - 1, 0, halfCols - 1); | |
| var b11 = b.subMatrix(0, halfRows - 1, 0, halfCols - 1); | |
| var a12 = a.subMatrix(0, halfRows - 1, halfCols, a.columns - 1); | |
| var b12 = b.subMatrix(0, halfRows - 1, halfCols, b.columns - 1); | |
| var a21 = a.subMatrix(halfRows, a.rows - 1, 0, halfCols - 1); | |
| var b21 = b.subMatrix(halfRows, b.rows - 1, 0, halfCols - 1); | |
| var a22 = a.subMatrix(halfRows, a.rows - 1, halfCols, a.columns - 1); | |
| var b22 = b.subMatrix(halfRows, b.rows - 1, halfCols, b.columns - 1); | |
| // Compute intermediate values. | |
| var m1 = blockMult(Matrix.add(a11, a22), Matrix.add(b11, b22), halfRows, halfCols); | |
| var m2 = blockMult(Matrix.add(a21, a22), b11, halfRows, halfCols); | |
| var m3 = blockMult(a11, Matrix.sub(b12, b22), halfRows, halfCols); | |
| var m4 = blockMult(a22, Matrix.sub(b21, b11), halfRows, halfCols); | |
| var m5 = blockMult(Matrix.add(a11, a12), b22, halfRows, halfCols); | |
| var m6 = blockMult(Matrix.sub(a21, a11), Matrix.add(b11, b12), halfRows, halfCols); | |
| var m7 = blockMult(Matrix.sub(a12, a22), Matrix.add(b21, b22), halfRows, halfCols); | |
| // Combine intermediate values into the output. | |
| var c11 = Matrix.add(m1, m4); | |
| c11.sub(m5); | |
| c11.add(m7); | |
| var c12 = Matrix.add(m3, m5); | |
| var c21 = Matrix.add(m2, m4); | |
| var c22 = Matrix.sub(m1, m2); | |
| c22.add(m3); | |
| c22.add(m6); | |
| // Crop output to the desired size (undo dynamic padding). | |
| var resultat = Matrix.zeros(2 * c11.rows, 2 * c11.columns); | |
| resultat = resultat.setSubMatrix(c11, 0, 0); | |
| resultat = resultat.setSubMatrix(c12, c11.rows, 0); | |
| resultat = resultat.setSubMatrix(c21, 0, c11.columns); | |
| resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns); | |
| return resultat.subMatrix(0, rows - 1, 0, cols - 1); | |
| } | |
| return blockMult(x, y, r, c); | |
| } | |
| /** | |
| * Returns a row-by-row scaled matrix | |
| * @param {number} [min=0] - Minimum scaled value | |
| * @param {number} [max=1] - Maximum scaled value | |
| * @return {Matrix} - The scaled matrix | |
| */ | |
| scaleRows(min, max) { | |
| min = min === undefined ? 0 : min; | |
| max = max === undefined ? 1 : max; | |
| if (min >= max) { | |
| throw new RangeError('min should be strictly smaller than max'); | |
| } | |
| var newMatrix = this.constructor.empty(this.rows, this.columns); | |
| for (var i = 0; i < this.rows; i++) { | |
| var scaled = ml_array_rescale_lib_es6(this.getRow(i), { min, max }); | |
| newMatrix.setRow(i, scaled); | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Returns a new column-by-column scaled matrix | |
| * @param {number} [min=0] - Minimum scaled value | |
| * @param {number} [max=1] - Maximum scaled value | |
| * @return {Matrix} - The new scaled matrix | |
| * @example | |
| * var matrix = new Matrix([[1,2],[-1,0]]); | |
| * var scaledMatrix = matrix.scaleColumns(); // [[1,1],[0,0]] | |
| */ | |
| scaleColumns(min, max) { | |
| min = min === undefined ? 0 : min; | |
| max = max === undefined ? 1 : max; | |
| if (min >= max) { | |
| throw new RangeError('min should be strictly smaller than max'); | |
| } | |
| var newMatrix = this.constructor.empty(this.rows, this.columns); | |
| for (var i = 0; i < this.columns; i++) { | |
| var scaled = ml_array_rescale_lib_es6(this.getColumn(i), { | |
| min: min, | |
| max: max | |
| }); | |
| newMatrix.setColumn(i, scaled); | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Returns the Kronecker product (also known as tensor product) between this and other | |
| * See https://en.wikipedia.org/wiki/Kronecker_product | |
| * @param {Matrix} other | |
| * @return {Matrix} | |
| */ | |
| kroneckerProduct(other) { | |
| other = this.constructor.checkMatrix(other); | |
| var m = this.rows; | |
| var n = this.columns; | |
| var p = other.rows; | |
| var q = other.columns; | |
| var result = new this.constructor[Symbol.species](m * p, n * q); | |
| for (var i = 0; i < m; i++) { | |
| for (var j = 0; j < n; j++) { | |
| for (var k = 0; k < p; k++) { | |
| for (var l = 0; l < q; l++) { | |
| result[p * i + k][q * j + l] = this.get(i, j) * other.get(k, l); | |
| } | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Transposes the matrix and returns a new one containing the result | |
| * @return {Matrix} | |
| */ | |
| transpose() { | |
| var result = new this.constructor[Symbol.species](this.columns, this.rows); | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| result.set(j, i, this.get(i, j)); | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Sorts the rows (in place) | |
| * @param {function} compareFunction - usual Array.prototype.sort comparison function | |
| * @return {Matrix} this | |
| */ | |
| sortRows(compareFunction) { | |
| if (compareFunction === undefined) compareFunction = compareNumbers; | |
| for (var i = 0; i < this.rows; i++) { | |
| this.setRow(i, this.getRow(i).sort(compareFunction)); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Sorts the columns (in place) | |
| * @param {function} compareFunction - usual Array.prototype.sort comparison function | |
| * @return {Matrix} this | |
| */ | |
| sortColumns(compareFunction) { | |
| if (compareFunction === undefined) compareFunction = compareNumbers; | |
| for (var i = 0; i < this.columns; i++) { | |
| this.setColumn(i, this.getColumn(i).sort(compareFunction)); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Returns a subset of the matrix | |
| * @param {number} startRow - First row index | |
| * @param {number} endRow - Last row index | |
| * @param {number} startColumn - First column index | |
| * @param {number} endColumn - Last column index | |
| * @return {Matrix} | |
| */ | |
| subMatrix(startRow, endRow, startColumn, endColumn) { | |
| checkRange(this, startRow, endRow, startColumn, endColumn); | |
| var newMatrix = new this.constructor[Symbol.species](endRow - startRow + 1, endColumn - startColumn + 1); | |
| for (var i = startRow; i <= endRow; i++) { | |
| for (var j = startColumn; j <= endColumn; j++) { | |
| newMatrix[i - startRow][j - startColumn] = this.get(i, j); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Returns a subset of the matrix based on an array of row indices | |
| * @param {Array} indices - Array containing the row indices | |
| * @param {number} [startColumn = 0] - First column index | |
| * @param {number} [endColumn = this.columns-1] - Last column index | |
| * @return {Matrix} | |
| */ | |
| subMatrixRow(indices, startColumn, endColumn) { | |
| if (startColumn === undefined) startColumn = 0; | |
| if (endColumn === undefined) endColumn = this.columns - 1; | |
| if ((startColumn > endColumn) || (startColumn < 0) || (startColumn >= this.columns) || (endColumn < 0) || (endColumn >= this.columns)) { | |
| throw new RangeError('Argument out of range'); | |
| } | |
| var newMatrix = new this.constructor[Symbol.species](indices.length, endColumn - startColumn + 1); | |
| for (var i = 0; i < indices.length; i++) { | |
| for (var j = startColumn; j <= endColumn; j++) { | |
| if (indices[i] < 0 || indices[i] >= this.rows) { | |
| throw new RangeError(`Row index out of range: ${indices[i]}`); | |
| } | |
| newMatrix.set(i, j - startColumn, this.get(indices[i], j)); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Returns a subset of the matrix based on an array of column indices | |
| * @param {Array} indices - Array containing the column indices | |
| * @param {number} [startRow = 0] - First row index | |
| * @param {number} [endRow = this.rows-1] - Last row index | |
| * @return {Matrix} | |
| */ | |
| subMatrixColumn(indices, startRow, endRow) { | |
| if (startRow === undefined) startRow = 0; | |
| if (endRow === undefined) endRow = this.rows - 1; | |
| if ((startRow > endRow) || (startRow < 0) || (startRow >= this.rows) || (endRow < 0) || (endRow >= this.rows)) { | |
| throw new RangeError('Argument out of range'); | |
| } | |
| var newMatrix = new this.constructor[Symbol.species](endRow - startRow + 1, indices.length); | |
| for (var i = 0; i < indices.length; i++) { | |
| for (var j = startRow; j <= endRow; j++) { | |
| if (indices[i] < 0 || indices[i] >= this.columns) { | |
| throw new RangeError(`Column index out of range: ${indices[i]}`); | |
| } | |
| newMatrix.set(j - startRow, i, this.get(j, indices[i])); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Set a part of the matrix to the given sub-matrix | |
| * @param {Matrix|Array< Array >} matrix - The source matrix from which to extract values. | |
| * @param {number} startRow - The index of the first row to set | |
| * @param {number} startColumn - The index of the first column to set | |
| * @return {Matrix} | |
| */ | |
| setSubMatrix(matrix, startRow, startColumn) { | |
| matrix = this.constructor.checkMatrix(matrix); | |
| var endRow = startRow + matrix.rows - 1; | |
| var endColumn = startColumn + matrix.columns - 1; | |
| checkRange(this, startRow, endRow, startColumn, endColumn); | |
| for (var i = 0; i < matrix.rows; i++) { | |
| for (var j = 0; j < matrix.columns; j++) { | |
| this[startRow + i][startColumn + j] = matrix.get(i, j); | |
| } | |
| } | |
| return this; | |
| } | |
| /** | |
| * Return a new matrix based on a selection of rows and columns | |
| * @param {Array<number>} rowIndices - The row indices to select. Order matters and an index can be more than once. | |
| * @param {Array<number>} columnIndices - The column indices to select. Order matters and an index can be use more than once. | |
| * @return {Matrix} The new matrix | |
| */ | |
| selection(rowIndices, columnIndices) { | |
| var indices = checkIndices(this, rowIndices, columnIndices); | |
| var newMatrix = new this.constructor[Symbol.species](rowIndices.length, columnIndices.length); | |
| for (var i = 0; i < indices.row.length; i++) { | |
| var rowIndex = indices.row[i]; | |
| for (var j = 0; j < indices.column.length; j++) { | |
| var columnIndex = indices.column[j]; | |
| newMatrix[i][j] = this.get(rowIndex, columnIndex); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| /** | |
| * Returns the trace of the matrix (sum of the diagonal elements) | |
| * @return {number} | |
| */ | |
| trace() { | |
| var min = Math.min(this.rows, this.columns); | |
| var trace = 0; | |
| for (var i = 0; i < min; i++) { | |
| trace += this.get(i, i); | |
| } | |
| return trace; | |
| } | |
| /* | |
| Matrix views | |
| */ | |
| /** | |
| * Returns a view of the transposition of the matrix | |
| * @return {MatrixTransposeView} | |
| */ | |
| transposeView() { | |
| return new transpose_MatrixTransposeView(this); | |
| } | |
| /** | |
| * Returns a view of the row vector with the given index | |
| * @param {number} row - row index of the vector | |
| * @return {MatrixRowView} | |
| */ | |
| rowView(row) { | |
| checkRowIndex(this, row); | |
| return new row_MatrixRowView(this, row); | |
| } | |
| /** | |
| * Returns a view of the column vector with the given index | |
| * @param {number} column - column index of the vector | |
| * @return {MatrixColumnView} | |
| */ | |
| columnView(column) { | |
| checkColumnIndex(this, column); | |
| return new column_MatrixColumnView(this, column); | |
| } | |
| /** | |
| * Returns a view of the matrix flipped in the row axis | |
| * @return {MatrixFlipRowView} | |
| */ | |
| flipRowView() { | |
| return new flipRow_MatrixFlipRowView(this); | |
| } | |
| /** | |
| * Returns a view of the matrix flipped in the column axis | |
| * @return {MatrixFlipColumnView} | |
| */ | |
| flipColumnView() { | |
| return new flipColumn_MatrixFlipColumnView(this); | |
| } | |
| /** | |
| * Returns a view of a submatrix giving the index boundaries | |
| * @param {number} startRow - first row index of the submatrix | |
| * @param {number} endRow - last row index of the submatrix | |
| * @param {number} startColumn - first column index of the submatrix | |
| * @param {number} endColumn - last column index of the submatrix | |
| * @return {MatrixSubView} | |
| */ | |
| subMatrixView(startRow, endRow, startColumn, endColumn) { | |
| return new sub_MatrixSubView(this, startRow, endRow, startColumn, endColumn); | |
| } | |
| /** | |
| * Returns a view of the cross of the row indices and the column indices | |
| * @example | |
| * // resulting vector is [[2], [2]] | |
| * var matrix = new Matrix([[1,2,3], [4,5,6]]).selectionView([0, 0], [1]) | |
| * @param {Array<number>} rowIndices | |
| * @param {Array<number>} columnIndices | |
| * @return {MatrixSelectionView} | |
| */ | |
| selectionView(rowIndices, columnIndices) { | |
| return new selection_MatrixSelectionView(this, rowIndices, columnIndices); | |
| } | |
| /** | |
| * Returns a view of the row indices | |
| * @example | |
| * // resulting vector is [[1,2,3], [1,2,3]] | |
| * var matrix = new Matrix([[1,2,3], [4,5,6]]).rowSelectionView([0, 0]) | |
| * @param {Array<number>} rowIndices | |
| * @return {MatrixRowSelectionView} | |
| */ | |
| rowSelectionView(rowIndices) { | |
| return new rowSelection_MatrixRowSelectionView(this, rowIndices); | |
| } | |
| /** | |
| * Returns a view of the column indices | |
| * @example | |
| * // resulting vector is [[2, 2], [5, 5]] | |
| * var matrix = new Matrix([[1,2,3], [4,5,6]]).columnSelectionView([1, 1]) | |
| * @param {Array<number>} columnIndices | |
| * @return {MatrixColumnSelectionView} | |
| */ | |
| columnSelectionView(columnIndices) { | |
| return new columnSelection_MatrixColumnSelectionView(this, columnIndices); | |
| } | |
| /** | |
| * Calculates and returns the determinant of a matrix as a Number | |
| * @example | |
| * new Matrix([[1,2,3], [4,5,6]]).det() | |
| * @return {number} | |
| */ | |
| det() { | |
| if (this.isSquare()) { | |
| var a, b, c, d; | |
| if (this.columns === 2) { | |
| // 2 x 2 matrix | |
| a = this.get(0, 0); | |
| b = this.get(0, 1); | |
| c = this.get(1, 0); | |
| d = this.get(1, 1); | |
| return a * d - (b * c); | |
| } else if (this.columns === 3) { | |
| // 3 x 3 matrix | |
| var subMatrix0, subMatrix1, subMatrix2; | |
| subMatrix0 = this.selectionView([1, 2], [1, 2]); | |
| subMatrix1 = this.selectionView([1, 2], [0, 2]); | |
| subMatrix2 = this.selectionView([1, 2], [0, 1]); | |
| a = this.get(0, 0); | |
| b = this.get(0, 1); | |
| c = this.get(0, 2); | |
| return a * subMatrix0.det() - b * subMatrix1.det() + c * subMatrix2.det(); | |
| } else { | |
| // general purpose determinant using the LU decomposition | |
| return new lu_LuDecomposition(this).determinant; | |
| } | |
| } else { | |
| throw Error('Determinant can only be calculated for a square matrix.'); | |
| } | |
| } | |
| /** | |
| * Returns inverse of a matrix if it exists or the pseudoinverse | |
| * @param {number} threshold - threshold for taking inverse of singular values (default = 1e-15) | |
| * @return {Matrix} the (pseudo)inverted matrix. | |
| */ | |
| pseudoInverse(threshold) { | |
| if (threshold === undefined) threshold = Number.EPSILON; | |
| var svdSolution = new svd_SingularValueDecomposition(this, { autoTranspose: true }); | |
| var U = svdSolution.leftSingularVectors; | |
| var V = svdSolution.rightSingularVectors; | |
| var s = svdSolution.diagonal; | |
| for (var i = 0; i < s.length; i++) { | |
| if (Math.abs(s[i]) > threshold) { | |
| s[i] = 1.0 / s[i]; | |
| } else { | |
| s[i] = 0.0; | |
| } | |
| } | |
| // convert list to diagonal | |
| s = this.constructor[Symbol.species].diag(s); | |
| return V.mmul(s.mmul(U.transposeView())); | |
| } | |
| /** | |
| * Creates an exact and independent copy of the matrix | |
| * @return {Matrix} | |
| */ | |
| clone() { | |
| var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns); | |
| for (var row = 0; row < this.rows; row++) { | |
| for (var column = 0; column < this.columns; column++) { | |
| newMatrix.set(row, column, this.get(row, column)); | |
| } | |
| } | |
| return newMatrix; | |
| } | |
| } | |
| Matrix.prototype.klass = 'Matrix'; | |
| function compareNumbers(a, b) { | |
| return a - b; | |
| } | |
| /* | |
| Synonyms | |
| */ | |
| Matrix.random = Matrix.rand; | |
| Matrix.diagonal = Matrix.diag; | |
| Matrix.prototype.diagonal = Matrix.prototype.diag; | |
| Matrix.identity = Matrix.eye; | |
| Matrix.prototype.negate = Matrix.prototype.neg; | |
| Matrix.prototype.tensorProduct = Matrix.prototype.kroneckerProduct; | |
| Matrix.prototype.determinant = Matrix.prototype.det; | |
| /* | |
| Add dynamically instance and static methods for mathematical operations | |
| */ | |
| var inplaceOperator = ` | |
| (function %name%(value) { | |
| if (typeof value === 'number') return this.%name%S(value); | |
| return this.%name%M(value); | |
| }) | |
| `; | |
| var inplaceOperatorScalar = ` | |
| (function %name%S(value) { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) %op% value); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var inplaceOperatorMatrix = ` | |
| (function %name%M(matrix) { | |
| matrix = this.constructor.checkMatrix(matrix); | |
| if (this.rows !== matrix.rows || | |
| this.columns !== matrix.columns) { | |
| throw new RangeError('Matrices dimensions must be equal'); | |
| } | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, this.get(i, j) %op% matrix.get(i, j)); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var staticOperator = ` | |
| (function %name%(matrix, value) { | |
| var newMatrix = new this[Symbol.species](matrix); | |
| return newMatrix.%name%(value); | |
| }) | |
| `; | |
| var inplaceMethod = ` | |
| (function %name%() { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, %method%(this.get(i, j))); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var staticMethod = ` | |
| (function %name%(matrix) { | |
| var newMatrix = new this[Symbol.species](matrix); | |
| return newMatrix.%name%(); | |
| }) | |
| `; | |
| var inplaceMethodWithArgs = ` | |
| (function %name%(%args%) { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, %method%(this.get(i, j), %args%)); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var staticMethodWithArgs = ` | |
| (function %name%(matrix, %args%) { | |
| var newMatrix = new this[Symbol.species](matrix); | |
| return newMatrix.%name%(%args%); | |
| }) | |
| `; | |
| var inplaceMethodWithOneArgScalar = ` | |
| (function %name%S(value) { | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, %method%(this.get(i, j), value)); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var inplaceMethodWithOneArgMatrix = ` | |
| (function %name%M(matrix) { | |
| matrix = this.constructor.checkMatrix(matrix); | |
| if (this.rows !== matrix.rows || | |
| this.columns !== matrix.columns) { | |
| throw new RangeError('Matrices dimensions must be equal'); | |
| } | |
| for (var i = 0; i < this.rows; i++) { | |
| for (var j = 0; j < this.columns; j++) { | |
| this.set(i, j, %method%(this.get(i, j), matrix.get(i, j))); | |
| } | |
| } | |
| return this; | |
| }) | |
| `; | |
| var inplaceMethodWithOneArg = ` | |
| (function %name%(value) { | |
| if (typeof value === 'number') return this.%name%S(value); | |
| return this.%name%M(value); | |
| }) | |
| `; | |
| var staticMethodWithOneArg = staticMethodWithArgs; | |
| var operators = [ | |
| // Arithmetic operators | |
| ['+', 'add'], | |
| ['-', 'sub', 'subtract'], | |
| ['*', 'mul', 'multiply'], | |
| ['/', 'div', 'divide'], | |
| ['%', 'mod', 'modulus'], | |
| // Bitwise operators | |
| ['&', 'and'], | |
| ['|', 'or'], | |
| ['^', 'xor'], | |
| ['<<', 'leftShift'], | |
| ['>>', 'signPropagatingRightShift'], | |
| ['>>>', 'rightShift', 'zeroFillRightShift'] | |
| ]; | |
| var i; | |
| var eval2 = eval; // eslint-disable-line no-eval | |
| for (var operator of operators) { | |
| var inplaceOp = eval2(fillTemplateFunction(inplaceOperator, { name: operator[1], op: operator[0] })); | |
| var inplaceOpS = eval2(fillTemplateFunction(inplaceOperatorScalar, { name: `${operator[1]}S`, op: operator[0] })); | |
| var inplaceOpM = eval2(fillTemplateFunction(inplaceOperatorMatrix, { name: `${operator[1]}M`, op: operator[0] })); | |
| var staticOp = eval2(fillTemplateFunction(staticOperator, { name: operator[1] })); | |
| for (i = 1; i < operator.length; i++) { | |
| Matrix.prototype[operator[i]] = inplaceOp; | |
| Matrix.prototype[`${operator[i]}S`] = inplaceOpS; | |
| Matrix.prototype[`${operator[i]}M`] = inplaceOpM; | |
| Matrix[operator[i]] = staticOp; | |
| } | |
| } | |
| var methods = [['~', 'not']]; | |
| [ | |
| 'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil', | |
| 'clz32', 'cos', 'cosh', 'exp', 'expm1', 'floor', 'fround', 'log', 'log1p', | |
| 'log10', 'log2', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc' | |
| ].forEach(function (mathMethod) { | |
| methods.push([`Math.${mathMethod}`, mathMethod]); | |
| }); | |
| for (var method of methods) { | |
| var inplaceMeth = eval2(fillTemplateFunction(inplaceMethod, { name: method[1], method: method[0] })); | |
| var staticMeth = eval2(fillTemplateFunction(staticMethod, { name: method[1] })); | |
| for (i = 1; i < method.length; i++) { | |
| Matrix.prototype[method[i]] = inplaceMeth; | |
| Matrix[method[i]] = staticMeth; | |
| } | |
| } | |
| var methodsWithArgs = [['Math.pow', 1, 'pow']]; | |
| for (var methodWithArg of methodsWithArgs) { | |
| var args = 'arg0'; | |
| for (i = 1; i < methodWithArg[1]; i++) { | |
| args += `, arg${i}`; | |
| } | |
| if (methodWithArg[1] !== 1) { | |
| var inplaceMethWithArgs = eval2(fillTemplateFunction(inplaceMethodWithArgs, { | |
| name: methodWithArg[2], | |
| method: methodWithArg[0], | |
| args: args | |
| })); | |
| var staticMethWithArgs = eval2(fillTemplateFunction(staticMethodWithArgs, { name: methodWithArg[2], args: args })); | |
| for (i = 2; i < methodWithArg.length; i++) { | |
| Matrix.prototype[methodWithArg[i]] = inplaceMethWithArgs; | |
| Matrix[methodWithArg[i]] = staticMethWithArgs; | |
| } | |
| } else { | |
| var tmplVar = { | |
| name: methodWithArg[2], | |
| args: args, | |
| method: methodWithArg[0] | |
| }; | |
| var inplaceMethod2 = eval2(fillTemplateFunction(inplaceMethodWithOneArg, tmplVar)); | |
| var inplaceMethodS = eval2(fillTemplateFunction(inplaceMethodWithOneArgScalar, tmplVar)); | |
| var inplaceMethodM = eval2(fillTemplateFunction(inplaceMethodWithOneArgMatrix, tmplVar)); | |
| var staticMethod2 = eval2(fillTemplateFunction(staticMethodWithOneArg, tmplVar)); | |
| for (i = 2; i < methodWithArg.length; i++) { | |
| Matrix.prototype[methodWithArg[i]] = inplaceMethod2; | |
| Matrix.prototype[`${methodWithArg[i]}M`] = inplaceMethodM; | |
| Matrix.prototype[`${methodWithArg[i]}S`] = inplaceMethodS; | |
| Matrix[methodWithArg[i]] = staticMethod2; | |
| } | |
| } | |
| } | |
| function fillTemplateFunction(template, values) { | |
| for (var value in values) { | |
| template = template.replace(new RegExp(`%${value}%`, 'g'), values[value]); | |
| } | |
| return template; | |
| } | |
| return Matrix; | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/matrix.js | |
| class matrix_Matrix extends AbstractMatrix(Array) { | |
| constructor(nRows, nColumns) { | |
| var i; | |
| if (arguments.length === 1 && typeof nRows === 'number') { | |
| return new Array(nRows); | |
| } | |
| if (matrix_Matrix.isMatrix(nRows)) { | |
| return nRows.clone(); | |
| } else if (Number.isInteger(nRows) && nRows > 0) { | |
| // Create an empty matrix | |
| super(nRows); | |
| if (Number.isInteger(nColumns) && nColumns > 0) { | |
| for (i = 0; i < nRows; i++) { | |
| this[i] = new Array(nColumns); | |
| } | |
| } else { | |
| throw new TypeError('nColumns must be a positive integer'); | |
| } | |
| } else if (Array.isArray(nRows)) { | |
| // Copy the values from the 2D array | |
| const matrix = nRows; | |
| nRows = matrix.length; | |
| nColumns = matrix[0].length; | |
| if (typeof nColumns !== 'number' || nColumns === 0) { | |
| throw new TypeError( | |
| 'Data must be a 2D array with at least one element' | |
| ); | |
| } | |
| super(nRows); | |
| for (i = 0; i < nRows; i++) { | |
| if (matrix[i].length !== nColumns) { | |
| throw new RangeError('Inconsistent array dimensions'); | |
| } | |
| this[i] = [].concat(matrix[i]); | |
| } | |
| } else { | |
| throw new TypeError( | |
| 'First argument must be a positive number or an array' | |
| ); | |
| } | |
| this.rows = nRows; | |
| this.columns = nColumns; | |
| return this; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this[rowIndex][columnIndex] = value; | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this[rowIndex][columnIndex]; | |
| } | |
| /** | |
| * Removes a row from the given index | |
| * @param {number} index - Row index | |
| * @return {Matrix} this | |
| */ | |
| removeRow(index) { | |
| checkRowIndex(this, index); | |
| if (this.rows === 1) { | |
| throw new RangeError('A matrix cannot have less than one row'); | |
| } | |
| this.splice(index, 1); | |
| this.rows -= 1; | |
| return this; | |
| } | |
| /** | |
| * Adds a row at the given index | |
| * @param {number} [index = this.rows] - Row index | |
| * @param {Array|Matrix} array - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| addRow(index, array) { | |
| if (array === undefined) { | |
| array = index; | |
| index = this.rows; | |
| } | |
| checkRowIndex(this, index, true); | |
| array = checkRowVector(this, array, true); | |
| this.splice(index, 0, array); | |
| this.rows += 1; | |
| return this; | |
| } | |
| /** | |
| * Removes a column from the given index | |
| * @param {number} index - Column index | |
| * @return {Matrix} this | |
| */ | |
| removeColumn(index) { | |
| checkColumnIndex(this, index); | |
| if (this.columns === 1) { | |
| throw new RangeError('A matrix cannot have less than one column'); | |
| } | |
| for (var i = 0; i < this.rows; i++) { | |
| this[i].splice(index, 1); | |
| } | |
| this.columns -= 1; | |
| return this; | |
| } | |
| /** | |
| * Adds a column at the given index | |
| * @param {number} [index = this.columns] - Column index | |
| * @param {Array|Matrix} array - Array or vector | |
| * @return {Matrix} this | |
| */ | |
| addColumn(index, array) { | |
| if (typeof array === 'undefined') { | |
| array = index; | |
| index = this.columns; | |
| } | |
| checkColumnIndex(this, index, true); | |
| array = checkColumnVector(this, array); | |
| for (var i = 0; i < this.rows; i++) { | |
| this[i].splice(index, 0, array[i]); | |
| } | |
| this.columns += 1; | |
| return this; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/wrap/WrapperMatrix1D.js | |
| class WrapperMatrix1D_WrapperMatrix1D extends AbstractMatrix() { | |
| /** | |
| * @class WrapperMatrix1D | |
| * @param {Array<number>} data | |
| * @param {object} [options] | |
| * @param {object} [options.rows = 1] | |
| */ | |
| constructor(data, options = {}) { | |
| const { rows = 1 } = options; | |
| if (data.length % rows !== 0) { | |
| throw new Error('the data length is not divisible by the number of rows'); | |
| } | |
| super(); | |
| this.rows = rows; | |
| this.columns = data.length / rows; | |
| this.data = data; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| var index = this._calculateIndex(rowIndex, columnIndex); | |
| this.data[index] = value; | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| var index = this._calculateIndex(rowIndex, columnIndex); | |
| return this.data[index]; | |
| } | |
| _calculateIndex(row, column) { | |
| return row * this.columns + column; | |
| } | |
| static get [Symbol.species]() { | |
| return matrix_Matrix; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/wrap/WrapperMatrix2D.js | |
| class WrapperMatrix2D_WrapperMatrix2D extends AbstractMatrix() { | |
| /** | |
| * @class WrapperMatrix2D | |
| * @param {Array<Array<number>>} data | |
| */ | |
| constructor(data) { | |
| super(); | |
| this.data = data; | |
| this.rows = data.length; | |
| this.columns = data[0].length; | |
| } | |
| set(rowIndex, columnIndex, value) { | |
| this.data[rowIndex][columnIndex] = value; | |
| return this; | |
| } | |
| get(rowIndex, columnIndex) { | |
| return this.data[rowIndex][columnIndex]; | |
| } | |
| static get [Symbol.species]() { | |
| return matrix_Matrix; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/wrap/wrap.js | |
| /** | |
| * @param {Array<Array<number>>|Array<number>} array | |
| * @param {object} [options] | |
| * @param {object} [options.rows = 1] | |
| * @return {WrapperMatrix1D|WrapperMatrix2D} | |
| */ | |
| function wrap(array, options) { | |
| if (Array.isArray(array)) { | |
| if (array[0] && Array.isArray(array[0])) { | |
| return new WrapperMatrix2D_WrapperMatrix2D(array); | |
| } else { | |
| return new WrapperMatrix1D_WrapperMatrix1D(array, options); | |
| } | |
| } else { | |
| throw new Error('the argument is not an array'); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/qr.js | |
| /** | |
| * @class QrDecomposition | |
| * @link https://github.com/lutzroeder/Mapack/blob/master/Source/QrDecomposition.cs | |
| * @param {Matrix} value | |
| */ | |
| class qr_QrDecomposition { | |
| constructor(value) { | |
| value = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(value); | |
| var qr = value.clone(); | |
| var m = value.rows; | |
| var n = value.columns; | |
| var rdiag = new Array(n); | |
| var i, j, k, s; | |
| for (k = 0; k < n; k++) { | |
| var nrm = 0; | |
| for (i = k; i < m; i++) { | |
| nrm = hypotenuse(nrm, qr.get(i, k)); | |
| } | |
| if (nrm !== 0) { | |
| if (qr.get(k, k) < 0) { | |
| nrm = -nrm; | |
| } | |
| for (i = k; i < m; i++) { | |
| qr.set(i, k, qr.get(i, k) / nrm); | |
| } | |
| qr.set(k, k, qr.get(k, k) + 1); | |
| for (j = k + 1; j < n; j++) { | |
| s = 0; | |
| for (i = k; i < m; i++) { | |
| s += qr.get(i, k) * qr.get(i, j); | |
| } | |
| s = -s / qr.get(k, k); | |
| for (i = k; i < m; i++) { | |
| qr.set(i, j, qr.get(i, j) + s * qr.get(i, k)); | |
| } | |
| } | |
| } | |
| rdiag[k] = -nrm; | |
| } | |
| this.QR = qr; | |
| this.Rdiag = rdiag; | |
| } | |
| /** | |
| * Solve a problem of least square (Ax=b) by using the QR decomposition. Useful when A is rectangular, but not working when A is singular. | |
| * Example : We search to approximate x, with A matrix shape m*n, x vector size n, b vector size m (m > n). We will use : | |
| * var qr = QrDecomposition(A); | |
| * var x = qr.solve(b); | |
| * @param {Matrix} value - Matrix 1D which is the vector b (in the equation Ax = b) | |
| * @return {Matrix} - The vector x | |
| */ | |
| solve(value) { | |
| value = matrix_Matrix.checkMatrix(value); | |
| var qr = this.QR; | |
| var m = qr.rows; | |
| if (value.rows !== m) { | |
| throw new Error('Matrix row dimensions must agree'); | |
| } | |
| if (!this.isFullRank()) { | |
| throw new Error('Matrix is rank deficient'); | |
| } | |
| var count = value.columns; | |
| var X = value.clone(); | |
| var n = qr.columns; | |
| var i, j, k, s; | |
| for (k = 0; k < n; k++) { | |
| for (j = 0; j < count; j++) { | |
| s = 0; | |
| for (i = k; i < m; i++) { | |
| s += qr[i][k] * X[i][j]; | |
| } | |
| s = -s / qr[k][k]; | |
| for (i = k; i < m; i++) { | |
| X[i][j] += s * qr[i][k]; | |
| } | |
| } | |
| } | |
| for (k = n - 1; k >= 0; k--) { | |
| for (j = 0; j < count; j++) { | |
| X[k][j] /= this.Rdiag[k]; | |
| } | |
| for (i = 0; i < k; i++) { | |
| for (j = 0; j < count; j++) { | |
| X[i][j] -= X[k][j] * qr[i][k]; | |
| } | |
| } | |
| } | |
| return X.subMatrix(0, n - 1, 0, count - 1); | |
| } | |
| /** | |
| * | |
| * @return {boolean} | |
| */ | |
| isFullRank() { | |
| var columns = this.QR.columns; | |
| for (var i = 0; i < columns; i++) { | |
| if (this.Rdiag[i] === 0) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get upperTriangularMatrix() { | |
| var qr = this.QR; | |
| var n = qr.columns; | |
| var X = new matrix_Matrix(n, n); | |
| var i, j; | |
| for (i = 0; i < n; i++) { | |
| for (j = 0; j < n; j++) { | |
| if (i < j) { | |
| X[i][j] = qr[i][j]; | |
| } else if (i === j) { | |
| X[i][j] = this.Rdiag[i]; | |
| } else { | |
| X[i][j] = 0; | |
| } | |
| } | |
| } | |
| return X; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get orthogonalMatrix() { | |
| var qr = this.QR; | |
| var rows = qr.rows; | |
| var columns = qr.columns; | |
| var X = new matrix_Matrix(rows, columns); | |
| var i, j, k, s; | |
| for (k = columns - 1; k >= 0; k--) { | |
| for (i = 0; i < rows; i++) { | |
| X[i][k] = 0; | |
| } | |
| X[k][k] = 1; | |
| for (j = k; j < columns; j++) { | |
| if (qr[k][k] !== 0) { | |
| s = 0; | |
| for (i = k; i < rows; i++) { | |
| s += qr[i][k] * X[i][j]; | |
| } | |
| s = -s / qr[k][k]; | |
| for (i = k; i < rows; i++) { | |
| X[i][j] += s * qr[i][k]; | |
| } | |
| } | |
| } | |
| } | |
| return X; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/decompositions.js | |
| /** | |
| * Computes the inverse of a Matrix | |
| * @param {Matrix} matrix | |
| * @param {boolean} [useSVD=false] | |
| * @return {Matrix} | |
| */ | |
| function inverse(matrix, useSVD = false) { | |
| matrix = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(matrix); | |
| if (useSVD) { | |
| return new svd_SingularValueDecomposition(matrix).inverse(); | |
| } else { | |
| return solve(matrix, matrix_Matrix.eye(matrix.rows)); | |
| } | |
| } | |
| /** | |
| * | |
| * @param {Matrix} leftHandSide | |
| * @param {Matrix} rightHandSide | |
| * @param {boolean} [useSVD = false] | |
| * @return {Matrix} | |
| */ | |
| function solve(leftHandSide, rightHandSide, useSVD = false) { | |
| leftHandSide = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(leftHandSide); | |
| rightHandSide = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(rightHandSide); | |
| if (useSVD) { | |
| return new svd_SingularValueDecomposition(leftHandSide).solve(rightHandSide); | |
| } else { | |
| return leftHandSide.isSquare() | |
| ? new lu_LuDecomposition(leftHandSide).solve(rightHandSide) | |
| : new qr_QrDecomposition(leftHandSide).solve(rightHandSide); | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/linearDependencies.js | |
| // function used by rowsDependencies | |
| function xrange(n, exception) { | |
| var range = []; | |
| for (var i = 0; i < n; i++) { | |
| if (i !== exception) { | |
| range.push(i); | |
| } | |
| } | |
| return range; | |
| } | |
| // function used by rowsDependencies | |
| function dependenciesOneRow( | |
| error, | |
| matrix, | |
| index, | |
| thresholdValue = 10e-10, | |
| thresholdError = 10e-10 | |
| ) { | |
| if (error > thresholdError) { | |
| return new Array(matrix.rows + 1).fill(0); | |
| } else { | |
| var returnArray = matrix.addRow(index, [0]); | |
| for (var i = 0; i < returnArray.rows; i++) { | |
| if (Math.abs(returnArray.get(i, 0)) < thresholdValue) { | |
| returnArray.set(i, 0, 0); | |
| } | |
| } | |
| return returnArray.to1DArray(); | |
| } | |
| } | |
| /** | |
| * Creates a matrix which represents the dependencies between rows. | |
| * If a row is a linear combination of others rows, the result will be a row with the coefficients of this combination. | |
| * For example : for A = [[2, 0, 0, 1], [0, 1, 6, 0], [0, 3, 0, 1], [0, 0, 1, 0], [0, 1, 2, 0]], the result will be [[0, 0, 0, 0, 0], [0, 0, 0, 4, 1], [0, 0, 0, 0, 0], [0, 0.25, 0, 0, -0.25], [0, 1, 0, -4, 0]] | |
| * @param {Matrix} matrix | |
| * @param {Object} [options] includes thresholdValue and thresholdError. | |
| * @param {number} [options.thresholdValue = 10e-10] If an absolute value is inferior to this threshold, it will equals zero. | |
| * @param {number} [options.thresholdError = 10e-10] If the error is inferior to that threshold, the linear combination found is accepted and the row is dependent from other rows. | |
| * @return {Matrix} the matrix which represents the dependencies between rows. | |
| */ | |
| function linearDependencies(matrix, options = {}) { | |
| const { thresholdValue = 10e-10, thresholdError = 10e-10 } = options; | |
| var n = matrix.rows; | |
| var results = new matrix_Matrix(n, n); | |
| for (var i = 0; i < n; i++) { | |
| var b = matrix_Matrix.columnVector(matrix.getRow(i)); | |
| var Abis = matrix.subMatrixRow(xrange(n, i)).transposeView(); | |
| var svd = new svd_SingularValueDecomposition(Abis); | |
| var x = svd.solve(b); | |
| var error = lib_es6( | |
| matrix_Matrix.sub(b, Abis.mmul(x)) | |
| .abs() | |
| .to1DArray() | |
| ); | |
| results.setRow( | |
| i, | |
| dependenciesOneRow(error, x, i, thresholdValue, thresholdError) | |
| ); | |
| } | |
| return results; | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/evd.js | |
| /** | |
| * @class EigenvalueDecomposition | |
| * @link https://github.com/lutzroeder/Mapack/blob/master/Source/EigenvalueDecomposition.cs | |
| * @param {Matrix} matrix | |
| * @param {object} [options] | |
| * @param {boolean} [options.assumeSymmetric=false] | |
| */ | |
| class evd_EigenvalueDecomposition { | |
| constructor(matrix, options = {}) { | |
| const { assumeSymmetric = false } = options; | |
| matrix = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(matrix); | |
| if (!matrix.isSquare()) { | |
| throw new Error('Matrix is not a square matrix'); | |
| } | |
| var n = matrix.columns; | |
| var V = getFilled2DArray(n, n, 0); | |
| var d = new Array(n); | |
| var e = new Array(n); | |
| var value = matrix; | |
| var i, j; | |
| var isSymmetric = false; | |
| if (assumeSymmetric) { | |
| isSymmetric = true; | |
| } else { | |
| isSymmetric = matrix.isSymmetric(); | |
| } | |
| if (isSymmetric) { | |
| for (i = 0; i < n; i++) { | |
| for (j = 0; j < n; j++) { | |
| V[i][j] = value.get(i, j); | |
| } | |
| } | |
| tred2(n, e, d, V); | |
| tql2(n, e, d, V); | |
| } else { | |
| var H = getFilled2DArray(n, n, 0); | |
| var ort = new Array(n); | |
| for (j = 0; j < n; j++) { | |
| for (i = 0; i < n; i++) { | |
| H[i][j] = value.get(i, j); | |
| } | |
| } | |
| orthes(n, H, ort, V); | |
| hqr2(n, e, d, V, H); | |
| } | |
| this.n = n; | |
| this.e = e; | |
| this.d = d; | |
| this.V = V; | |
| } | |
| /** | |
| * | |
| * @return {Array<number>} | |
| */ | |
| get realEigenvalues() { | |
| return this.d; | |
| } | |
| /** | |
| * | |
| * @return {Array<number>} | |
| */ | |
| get imaginaryEigenvalues() { | |
| return this.e; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get eigenvectorMatrix() { | |
| if (!matrix_Matrix.isMatrix(this.V)) { | |
| this.V = new matrix_Matrix(this.V); | |
| } | |
| return this.V; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get diagonalMatrix() { | |
| var n = this.n; | |
| var e = this.e; | |
| var d = this.d; | |
| var X = new matrix_Matrix(n, n); | |
| var i, j; | |
| for (i = 0; i < n; i++) { | |
| for (j = 0; j < n; j++) { | |
| X[i][j] = 0; | |
| } | |
| X[i][i] = d[i]; | |
| if (e[i] > 0) { | |
| X[i][i + 1] = e[i]; | |
| } else if (e[i] < 0) { | |
| X[i][i - 1] = e[i]; | |
| } | |
| } | |
| return X; | |
| } | |
| } | |
| function tred2(n, e, d, V) { | |
| var f, g, h, i, j, k, hh, scale; | |
| for (j = 0; j < n; j++) { | |
| d[j] = V[n - 1][j]; | |
| } | |
| for (i = n - 1; i > 0; i--) { | |
| scale = 0; | |
| h = 0; | |
| for (k = 0; k < i; k++) { | |
| scale = scale + Math.abs(d[k]); | |
| } | |
| if (scale === 0) { | |
| e[i] = d[i - 1]; | |
| for (j = 0; j < i; j++) { | |
| d[j] = V[i - 1][j]; | |
| V[i][j] = 0; | |
| V[j][i] = 0; | |
| } | |
| } else { | |
| for (k = 0; k < i; k++) { | |
| d[k] /= scale; | |
| h += d[k] * d[k]; | |
| } | |
| f = d[i - 1]; | |
| g = Math.sqrt(h); | |
| if (f > 0) { | |
| g = -g; | |
| } | |
| e[i] = scale * g; | |
| h = h - f * g; | |
| d[i - 1] = f - g; | |
| for (j = 0; j < i; j++) { | |
| e[j] = 0; | |
| } | |
| for (j = 0; j < i; j++) { | |
| f = d[j]; | |
| V[j][i] = f; | |
| g = e[j] + V[j][j] * f; | |
| for (k = j + 1; k <= i - 1; k++) { | |
| g += V[k][j] * d[k]; | |
| e[k] += V[k][j] * f; | |
| } | |
| e[j] = g; | |
| } | |
| f = 0; | |
| for (j = 0; j < i; j++) { | |
| e[j] /= h; | |
| f += e[j] * d[j]; | |
| } | |
| hh = f / (h + h); | |
| for (j = 0; j < i; j++) { | |
| e[j] -= hh * d[j]; | |
| } | |
| for (j = 0; j < i; j++) { | |
| f = d[j]; | |
| g = e[j]; | |
| for (k = j; k <= i - 1; k++) { | |
| V[k][j] -= f * e[k] + g * d[k]; | |
| } | |
| d[j] = V[i - 1][j]; | |
| V[i][j] = 0; | |
| } | |
| } | |
| d[i] = h; | |
| } | |
| for (i = 0; i < n - 1; i++) { | |
| V[n - 1][i] = V[i][i]; | |
| V[i][i] = 1; | |
| h = d[i + 1]; | |
| if (h !== 0) { | |
| for (k = 0; k <= i; k++) { | |
| d[k] = V[k][i + 1] / h; | |
| } | |
| for (j = 0; j <= i; j++) { | |
| g = 0; | |
| for (k = 0; k <= i; k++) { | |
| g += V[k][i + 1] * V[k][j]; | |
| } | |
| for (k = 0; k <= i; k++) { | |
| V[k][j] -= g * d[k]; | |
| } | |
| } | |
| } | |
| for (k = 0; k <= i; k++) { | |
| V[k][i + 1] = 0; | |
| } | |
| } | |
| for (j = 0; j < n; j++) { | |
| d[j] = V[n - 1][j]; | |
| V[n - 1][j] = 0; | |
| } | |
| V[n - 1][n - 1] = 1; | |
| e[0] = 0; | |
| } | |
| function tql2(n, e, d, V) { | |
| var g, h, i, j, k, l, m, p, r, dl1, c, c2, c3, el1, s, s2, iter; | |
| for (i = 1; i < n; i++) { | |
| e[i - 1] = e[i]; | |
| } | |
| e[n - 1] = 0; | |
| var f = 0; | |
| var tst1 = 0; | |
| var eps = Number.EPSILON; | |
| for (l = 0; l < n; l++) { | |
| tst1 = Math.max(tst1, Math.abs(d[l]) + Math.abs(e[l])); | |
| m = l; | |
| while (m < n) { | |
| if (Math.abs(e[m]) <= eps * tst1) { | |
| break; | |
| } | |
| m++; | |
| } | |
| if (m > l) { | |
| iter = 0; | |
| do { | |
| iter = iter + 1; | |
| g = d[l]; | |
| p = (d[l + 1] - g) / (2 * e[l]); | |
| r = hypotenuse(p, 1); | |
| if (p < 0) { | |
| r = -r; | |
| } | |
| d[l] = e[l] / (p + r); | |
| d[l + 1] = e[l] * (p + r); | |
| dl1 = d[l + 1]; | |
| h = g - d[l]; | |
| for (i = l + 2; i < n; i++) { | |
| d[i] -= h; | |
| } | |
| f = f + h; | |
| p = d[m]; | |
| c = 1; | |
| c2 = c; | |
| c3 = c; | |
| el1 = e[l + 1]; | |
| s = 0; | |
| s2 = 0; | |
| for (i = m - 1; i >= l; i--) { | |
| c3 = c2; | |
| c2 = c; | |
| s2 = s; | |
| g = c * e[i]; | |
| h = c * p; | |
| r = hypotenuse(p, e[i]); | |
| e[i + 1] = s * r; | |
| s = e[i] / r; | |
| c = p / r; | |
| p = c * d[i] - s * g; | |
| d[i + 1] = h + s * (c * g + s * d[i]); | |
| for (k = 0; k < n; k++) { | |
| h = V[k][i + 1]; | |
| V[k][i + 1] = s * V[k][i] + c * h; | |
| V[k][i] = c * V[k][i] - s * h; | |
| } | |
| } | |
| p = -s * s2 * c3 * el1 * e[l] / dl1; | |
| e[l] = s * p; | |
| d[l] = c * p; | |
| } while (Math.abs(e[l]) > eps * tst1); | |
| } | |
| d[l] = d[l] + f; | |
| e[l] = 0; | |
| } | |
| for (i = 0; i < n - 1; i++) { | |
| k = i; | |
| p = d[i]; | |
| for (j = i + 1; j < n; j++) { | |
| if (d[j] < p) { | |
| k = j; | |
| p = d[j]; | |
| } | |
| } | |
| if (k !== i) { | |
| d[k] = d[i]; | |
| d[i] = p; | |
| for (j = 0; j < n; j++) { | |
| p = V[j][i]; | |
| V[j][i] = V[j][k]; | |
| V[j][k] = p; | |
| } | |
| } | |
| } | |
| } | |
| function orthes(n, H, ort, V) { | |
| var low = 0; | |
| var high = n - 1; | |
| var f, g, h, i, j, m; | |
| var scale; | |
| for (m = low + 1; m <= high - 1; m++) { | |
| scale = 0; | |
| for (i = m; i <= high; i++) { | |
| scale = scale + Math.abs(H[i][m - 1]); | |
| } | |
| if (scale !== 0) { | |
| h = 0; | |
| for (i = high; i >= m; i--) { | |
| ort[i] = H[i][m - 1] / scale; | |
| h += ort[i] * ort[i]; | |
| } | |
| g = Math.sqrt(h); | |
| if (ort[m] > 0) { | |
| g = -g; | |
| } | |
| h = h - ort[m] * g; | |
| ort[m] = ort[m] - g; | |
| for (j = m; j < n; j++) { | |
| f = 0; | |
| for (i = high; i >= m; i--) { | |
| f += ort[i] * H[i][j]; | |
| } | |
| f = f / h; | |
| for (i = m; i <= high; i++) { | |
| H[i][j] -= f * ort[i]; | |
| } | |
| } | |
| for (i = 0; i <= high; i++) { | |
| f = 0; | |
| for (j = high; j >= m; j--) { | |
| f += ort[j] * H[i][j]; | |
| } | |
| f = f / h; | |
| for (j = m; j <= high; j++) { | |
| H[i][j] -= f * ort[j]; | |
| } | |
| } | |
| ort[m] = scale * ort[m]; | |
| H[m][m - 1] = scale * g; | |
| } | |
| } | |
| for (i = 0; i < n; i++) { | |
| for (j = 0; j < n; j++) { | |
| V[i][j] = i === j ? 1 : 0; | |
| } | |
| } | |
| for (m = high - 1; m >= low + 1; m--) { | |
| if (H[m][m - 1] !== 0) { | |
| for (i = m + 1; i <= high; i++) { | |
| ort[i] = H[i][m - 1]; | |
| } | |
| for (j = m; j <= high; j++) { | |
| g = 0; | |
| for (i = m; i <= high; i++) { | |
| g += ort[i] * V[i][j]; | |
| } | |
| g = g / ort[m] / H[m][m - 1]; | |
| for (i = m; i <= high; i++) { | |
| V[i][j] += g * ort[i]; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| function hqr2(nn, e, d, V, H) { | |
| var n = nn - 1; | |
| var low = 0; | |
| var high = nn - 1; | |
| var eps = Number.EPSILON; | |
| var exshift = 0; | |
| var norm = 0; | |
| var p = 0; | |
| var q = 0; | |
| var r = 0; | |
| var s = 0; | |
| var z = 0; | |
| var iter = 0; | |
| var i, j, k, l, m, t, w, x, y; | |
| var ra, sa, vr, vi; | |
| var notlast, cdivres; | |
| for (i = 0; i < nn; i++) { | |
| if (i < low || i > high) { | |
| d[i] = H[i][i]; | |
| e[i] = 0; | |
| } | |
| for (j = Math.max(i - 1, 0); j < nn; j++) { | |
| norm = norm + Math.abs(H[i][j]); | |
| } | |
| } | |
| while (n >= low) { | |
| l = n; | |
| while (l > low) { | |
| s = Math.abs(H[l - 1][l - 1]) + Math.abs(H[l][l]); | |
| if (s === 0) { | |
| s = norm; | |
| } | |
| if (Math.abs(H[l][l - 1]) < eps * s) { | |
| break; | |
| } | |
| l--; | |
| } | |
| if (l === n) { | |
| H[n][n] = H[n][n] + exshift; | |
| d[n] = H[n][n]; | |
| e[n] = 0; | |
| n--; | |
| iter = 0; | |
| } else if (l === n - 1) { | |
| w = H[n][n - 1] * H[n - 1][n]; | |
| p = (H[n - 1][n - 1] - H[n][n]) / 2; | |
| q = p * p + w; | |
| z = Math.sqrt(Math.abs(q)); | |
| H[n][n] = H[n][n] + exshift; | |
| H[n - 1][n - 1] = H[n - 1][n - 1] + exshift; | |
| x = H[n][n]; | |
| if (q >= 0) { | |
| z = p >= 0 ? p + z : p - z; | |
| d[n - 1] = x + z; | |
| d[n] = d[n - 1]; | |
| if (z !== 0) { | |
| d[n] = x - w / z; | |
| } | |
| e[n - 1] = 0; | |
| e[n] = 0; | |
| x = H[n][n - 1]; | |
| s = Math.abs(x) + Math.abs(z); | |
| p = x / s; | |
| q = z / s; | |
| r = Math.sqrt(p * p + q * q); | |
| p = p / r; | |
| q = q / r; | |
| for (j = n - 1; j < nn; j++) { | |
| z = H[n - 1][j]; | |
| H[n - 1][j] = q * z + p * H[n][j]; | |
| H[n][j] = q * H[n][j] - p * z; | |
| } | |
| for (i = 0; i <= n; i++) { | |
| z = H[i][n - 1]; | |
| H[i][n - 1] = q * z + p * H[i][n]; | |
| H[i][n] = q * H[i][n] - p * z; | |
| } | |
| for (i = low; i <= high; i++) { | |
| z = V[i][n - 1]; | |
| V[i][n - 1] = q * z + p * V[i][n]; | |
| V[i][n] = q * V[i][n] - p * z; | |
| } | |
| } else { | |
| d[n - 1] = x + p; | |
| d[n] = x + p; | |
| e[n - 1] = z; | |
| e[n] = -z; | |
| } | |
| n = n - 2; | |
| iter = 0; | |
| } else { | |
| x = H[n][n]; | |
| y = 0; | |
| w = 0; | |
| if (l < n) { | |
| y = H[n - 1][n - 1]; | |
| w = H[n][n - 1] * H[n - 1][n]; | |
| } | |
| if (iter === 10) { | |
| exshift += x; | |
| for (i = low; i <= n; i++) { | |
| H[i][i] -= x; | |
| } | |
| s = Math.abs(H[n][n - 1]) + Math.abs(H[n - 1][n - 2]); | |
| x = y = 0.75 * s; | |
| w = -0.4375 * s * s; | |
| } | |
| if (iter === 30) { | |
| s = (y - x) / 2; | |
| s = s * s + w; | |
| if (s > 0) { | |
| s = Math.sqrt(s); | |
| if (y < x) { | |
| s = -s; | |
| } | |
| s = x - w / ((y - x) / 2 + s); | |
| for (i = low; i <= n; i++) { | |
| H[i][i] -= s; | |
| } | |
| exshift += s; | |
| x = y = w = 0.964; | |
| } | |
| } | |
| iter = iter + 1; | |
| m = n - 2; | |
| while (m >= l) { | |
| z = H[m][m]; | |
| r = x - z; | |
| s = y - z; | |
| p = (r * s - w) / H[m + 1][m] + H[m][m + 1]; | |
| q = H[m + 1][m + 1] - z - r - s; | |
| r = H[m + 2][m + 1]; | |
| s = Math.abs(p) + Math.abs(q) + Math.abs(r); | |
| p = p / s; | |
| q = q / s; | |
| r = r / s; | |
| if (m === l) { | |
| break; | |
| } | |
| if ( | |
| Math.abs(H[m][m - 1]) * (Math.abs(q) + Math.abs(r)) < | |
| eps * | |
| (Math.abs(p) * | |
| (Math.abs(H[m - 1][m - 1]) + | |
| Math.abs(z) + | |
| Math.abs(H[m + 1][m + 1]))) | |
| ) { | |
| break; | |
| } | |
| m--; | |
| } | |
| for (i = m + 2; i <= n; i++) { | |
| H[i][i - 2] = 0; | |
| if (i > m + 2) { | |
| H[i][i - 3] = 0; | |
| } | |
| } | |
| for (k = m; k <= n - 1; k++) { | |
| notlast = k !== n - 1; | |
| if (k !== m) { | |
| p = H[k][k - 1]; | |
| q = H[k + 1][k - 1]; | |
| r = notlast ? H[k + 2][k - 1] : 0; | |
| x = Math.abs(p) + Math.abs(q) + Math.abs(r); | |
| if (x !== 0) { | |
| p = p / x; | |
| q = q / x; | |
| r = r / x; | |
| } | |
| } | |
| if (x === 0) { | |
| break; | |
| } | |
| s = Math.sqrt(p * p + q * q + r * r); | |
| if (p < 0) { | |
| s = -s; | |
| } | |
| if (s !== 0) { | |
| if (k !== m) { | |
| H[k][k - 1] = -s * x; | |
| } else if (l !== m) { | |
| H[k][k - 1] = -H[k][k - 1]; | |
| } | |
| p = p + s; | |
| x = p / s; | |
| y = q / s; | |
| z = r / s; | |
| q = q / p; | |
| r = r / p; | |
| for (j = k; j < nn; j++) { | |
| p = H[k][j] + q * H[k + 1][j]; | |
| if (notlast) { | |
| p = p + r * H[k + 2][j]; | |
| H[k + 2][j] = H[k + 2][j] - p * z; | |
| } | |
| H[k][j] = H[k][j] - p * x; | |
| H[k + 1][j] = H[k + 1][j] - p * y; | |
| } | |
| for (i = 0; i <= Math.min(n, k + 3); i++) { | |
| p = x * H[i][k] + y * H[i][k + 1]; | |
| if (notlast) { | |
| p = p + z * H[i][k + 2]; | |
| H[i][k + 2] = H[i][k + 2] - p * r; | |
| } | |
| H[i][k] = H[i][k] - p; | |
| H[i][k + 1] = H[i][k + 1] - p * q; | |
| } | |
| for (i = low; i <= high; i++) { | |
| p = x * V[i][k] + y * V[i][k + 1]; | |
| if (notlast) { | |
| p = p + z * V[i][k + 2]; | |
| V[i][k + 2] = V[i][k + 2] - p * r; | |
| } | |
| V[i][k] = V[i][k] - p; | |
| V[i][k + 1] = V[i][k + 1] - p * q; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (norm === 0) { | |
| return; | |
| } | |
| for (n = nn - 1; n >= 0; n--) { | |
| p = d[n]; | |
| q = e[n]; | |
| if (q === 0) { | |
| l = n; | |
| H[n][n] = 1; | |
| for (i = n - 1; i >= 0; i--) { | |
| w = H[i][i] - p; | |
| r = 0; | |
| for (j = l; j <= n; j++) { | |
| r = r + H[i][j] * H[j][n]; | |
| } | |
| if (e[i] < 0) { | |
| z = w; | |
| s = r; | |
| } else { | |
| l = i; | |
| if (e[i] === 0) { | |
| H[i][n] = w !== 0 ? -r / w : -r / (eps * norm); | |
| } else { | |
| x = H[i][i + 1]; | |
| y = H[i + 1][i]; | |
| q = (d[i] - p) * (d[i] - p) + e[i] * e[i]; | |
| t = (x * s - z * r) / q; | |
| H[i][n] = t; | |
| H[i + 1][n] = | |
| Math.abs(x) > Math.abs(z) ? (-r - w * t) / x : (-s - y * t) / z; | |
| } | |
| t = Math.abs(H[i][n]); | |
| if (eps * t * t > 1) { | |
| for (j = i; j <= n; j++) { | |
| H[j][n] = H[j][n] / t; | |
| } | |
| } | |
| } | |
| } | |
| } else if (q < 0) { | |
| l = n - 1; | |
| if (Math.abs(H[n][n - 1]) > Math.abs(H[n - 1][n])) { | |
| H[n - 1][n - 1] = q / H[n][n - 1]; | |
| H[n - 1][n] = -(H[n][n] - p) / H[n][n - 1]; | |
| } else { | |
| cdivres = cdiv(0, -H[n - 1][n], H[n - 1][n - 1] - p, q); | |
| H[n - 1][n - 1] = cdivres[0]; | |
| H[n - 1][n] = cdivres[1]; | |
| } | |
| H[n][n - 1] = 0; | |
| H[n][n] = 1; | |
| for (i = n - 2; i >= 0; i--) { | |
| ra = 0; | |
| sa = 0; | |
| for (j = l; j <= n; j++) { | |
| ra = ra + H[i][j] * H[j][n - 1]; | |
| sa = sa + H[i][j] * H[j][n]; | |
| } | |
| w = H[i][i] - p; | |
| if (e[i] < 0) { | |
| z = w; | |
| r = ra; | |
| s = sa; | |
| } else { | |
| l = i; | |
| if (e[i] === 0) { | |
| cdivres = cdiv(-ra, -sa, w, q); | |
| H[i][n - 1] = cdivres[0]; | |
| H[i][n] = cdivres[1]; | |
| } else { | |
| x = H[i][i + 1]; | |
| y = H[i + 1][i]; | |
| vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q; | |
| vi = (d[i] - p) * 2 * q; | |
| if (vr === 0 && vi === 0) { | |
| vr = | |
| eps * | |
| norm * | |
| (Math.abs(w) + | |
| Math.abs(q) + | |
| Math.abs(x) + | |
| Math.abs(y) + | |
| Math.abs(z)); | |
| } | |
| cdivres = cdiv( | |
| x * r - z * ra + q * sa, | |
| x * s - z * sa - q * ra, | |
| vr, | |
| vi | |
| ); | |
| H[i][n - 1] = cdivres[0]; | |
| H[i][n] = cdivres[1]; | |
| if (Math.abs(x) > Math.abs(z) + Math.abs(q)) { | |
| H[i + 1][n - 1] = (-ra - w * H[i][n - 1] + q * H[i][n]) / x; | |
| H[i + 1][n] = (-sa - w * H[i][n] - q * H[i][n - 1]) / x; | |
| } else { | |
| cdivres = cdiv(-r - y * H[i][n - 1], -s - y * H[i][n], z, q); | |
| H[i + 1][n - 1] = cdivres[0]; | |
| H[i + 1][n] = cdivres[1]; | |
| } | |
| } | |
| t = Math.max(Math.abs(H[i][n - 1]), Math.abs(H[i][n])); | |
| if (eps * t * t > 1) { | |
| for (j = i; j <= n; j++) { | |
| H[j][n - 1] = H[j][n - 1] / t; | |
| H[j][n] = H[j][n] / t; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| for (i = 0; i < nn; i++) { | |
| if (i < low || i > high) { | |
| for (j = i; j < nn; j++) { | |
| V[i][j] = H[i][j]; | |
| } | |
| } | |
| } | |
| for (j = nn - 1; j >= low; j--) { | |
| for (i = low; i <= high; i++) { | |
| z = 0; | |
| for (k = low; k <= Math.min(j, high); k++) { | |
| z = z + V[i][k] * H[k][j]; | |
| } | |
| V[i][j] = z; | |
| } | |
| } | |
| } | |
| function cdiv(xr, xi, yr, yi) { | |
| var r, d; | |
| if (Math.abs(yr) > Math.abs(yi)) { | |
| r = yi / yr; | |
| d = yr + r * yi; | |
| return [(xr + r * xi) / d, (xi - r * xr) / d]; | |
| } else { | |
| r = yr / yi; | |
| d = yi + r * yr; | |
| return [(r * xr + xi) / d, (r * xi - xr) / d]; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/dc/cholesky.js | |
| /** | |
| * @class CholeskyDecomposition | |
| * @link https://github.com/lutzroeder/Mapack/blob/master/Source/CholeskyDecomposition.cs | |
| * @param {Matrix} value | |
| */ | |
| class cholesky_CholeskyDecomposition { | |
| constructor(value) { | |
| value = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(value); | |
| if (!value.isSymmetric()) { | |
| throw new Error('Matrix is not symmetric'); | |
| } | |
| var a = value; | |
| var dimension = a.rows; | |
| var l = new matrix_Matrix(dimension, dimension); | |
| var positiveDefinite = true; | |
| var i, j, k; | |
| for (j = 0; j < dimension; j++) { | |
| var Lrowj = l[j]; | |
| var d = 0; | |
| for (k = 0; k < j; k++) { | |
| var Lrowk = l[k]; | |
| var s = 0; | |
| for (i = 0; i < k; i++) { | |
| s += Lrowk[i] * Lrowj[i]; | |
| } | |
| Lrowj[k] = s = (a.get(j, k) - s) / l[k][k]; | |
| d = d + s * s; | |
| } | |
| d = a.get(j, j) - d; | |
| positiveDefinite &= d > 0; | |
| l[j][j] = Math.sqrt(Math.max(d, 0)); | |
| for (k = j + 1; k < dimension; k++) { | |
| l[j][k] = 0; | |
| } | |
| } | |
| if (!positiveDefinite) { | |
| throw new Error('Matrix is not positive definite'); | |
| } | |
| this.L = l; | |
| } | |
| /** | |
| * | |
| * @param {Matrix} value | |
| * @return {Matrix} | |
| */ | |
| solve(value) { | |
| value = WrapperMatrix2D_WrapperMatrix2D.checkMatrix(value); | |
| var l = this.L; | |
| var dimension = l.rows; | |
| if (value.rows !== dimension) { | |
| throw new Error('Matrix dimensions do not match'); | |
| } | |
| var count = value.columns; | |
| var B = value.clone(); | |
| var i, j, k; | |
| for (k = 0; k < dimension; k++) { | |
| for (j = 0; j < count; j++) { | |
| for (i = 0; i < k; i++) { | |
| B[k][j] -= B[i][j] * l[k][i]; | |
| } | |
| B[k][j] /= l[k][k]; | |
| } | |
| } | |
| for (k = dimension - 1; k >= 0; k--) { | |
| for (j = 0; j < count; j++) { | |
| for (i = k + 1; i < dimension; i++) { | |
| B[k][j] -= B[i][j] * l[i][k]; | |
| } | |
| B[k][j] /= l[k][k]; | |
| } | |
| } | |
| return B; | |
| } | |
| /** | |
| * | |
| * @return {Matrix} | |
| */ | |
| get lowerTriangularMatrix() { | |
| return this.L; | |
| } | |
| } | |
| // CONCATENATED MODULE: ./node_modules/ml-matrix/src/index.js | |
| /* concated harmony reexport default */__webpack_require__.d(__webpack_exports__, "default", function() { return matrix_Matrix; }); | |
| /* concated harmony reexport Matrix */__webpack_require__.d(__webpack_exports__, "Matrix", function() { return matrix_Matrix; }); | |
| /* concated harmony reexport abstractMatrix */__webpack_require__.d(__webpack_exports__, "abstractMatrix", function() { return AbstractMatrix; }); | |
| /* concated harmony reexport wrap */__webpack_require__.d(__webpack_exports__, "wrap", function() { return wrap; }); | |
| /* concated harmony reexport WrapperMatrix2D */__webpack_require__.d(__webpack_exports__, "WrapperMatrix2D", function() { return WrapperMatrix2D_WrapperMatrix2D; }); | |
| /* concated harmony reexport WrapperMatrix1D */__webpack_require__.d(__webpack_exports__, "WrapperMatrix1D", function() { return WrapperMatrix1D_WrapperMatrix1D; }); | |
| /* concated harmony reexport solve */__webpack_require__.d(__webpack_exports__, "solve", function() { return solve; }); | |
| /* concated harmony reexport inverse */__webpack_require__.d(__webpack_exports__, "inverse", function() { return inverse; }); | |
| /* concated harmony reexport linearDependencies */__webpack_require__.d(__webpack_exports__, "linearDependencies", function() { return linearDependencies; }); | |
| /* concated harmony reexport SingularValueDecomposition */__webpack_require__.d(__webpack_exports__, "SingularValueDecomposition", function() { return svd_SingularValueDecomposition; }); | |
| /* concated harmony reexport SVD */__webpack_require__.d(__webpack_exports__, "SVD", function() { return svd_SingularValueDecomposition; }); | |
| /* concated harmony reexport EigenvalueDecomposition */__webpack_require__.d(__webpack_exports__, "EigenvalueDecomposition", function() { return evd_EigenvalueDecomposition; }); | |
| /* concated harmony reexport EVD */__webpack_require__.d(__webpack_exports__, "EVD", function() { return evd_EigenvalueDecomposition; }); | |
| /* concated harmony reexport CholeskyDecomposition */__webpack_require__.d(__webpack_exports__, "CholeskyDecomposition", function() { return cholesky_CholeskyDecomposition; }); | |
| /* concated harmony reexport CHO */__webpack_require__.d(__webpack_exports__, "CHO", function() { return cholesky_CholeskyDecomposition; }); | |
| /* concated harmony reexport LuDecomposition */__webpack_require__.d(__webpack_exports__, "LuDecomposition", function() { return lu_LuDecomposition; }); | |
| /* concated harmony reexport LU */__webpack_require__.d(__webpack_exports__, "LU", function() { return lu_LuDecomposition; }); | |
| /* concated harmony reexport QrDecomposition */__webpack_require__.d(__webpack_exports__, "QrDecomposition", function() { return qr_QrDecomposition; }); | |
| /* concated harmony reexport QR */__webpack_require__.d(__webpack_exports__, "QR", function() { return qr_QrDecomposition; }); | |
| /***/ }) | |
| /******/ ]); | |
| }); |