| | |
| | (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) { |
| | |
| | var installedModules = {}; |
| | |
| | |
| | function __webpack_require__(moduleId) { |
| | |
| | |
| | if(installedModules[moduleId]) { |
| | return installedModules[moduleId].exports; |
| | } |
| | |
| | var module = installedModules[moduleId] = { |
| | i: moduleId, |
| | l: false, |
| | exports: {} |
| | }; |
| | |
| | |
| | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); |
| | |
| | |
| | module.l = true; |
| | |
| | |
| | return module.exports; |
| | } |
| | |
| | |
| | |
| | __webpack_require__.m = modules; |
| | |
| | |
| | __webpack_require__.c = installedModules; |
| | |
| | |
| | __webpack_require__.d = function(exports, name, getter) { |
| | if(!__webpack_require__.o(exports, name)) { |
| | Object.defineProperty(exports, name, { enumerable: true, get: getter }); |
| | } |
| | }; |
| | |
| | |
| | __webpack_require__.r = function(exports) { |
| | if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { |
| | Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |
| | } |
| | Object.defineProperty(exports, '__esModule', { value: true }); |
| | }; |
| | |
| | |
| | |
| | |
| | |
| | |
| | __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; |
| | }; |
| | |
| | |
| | __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; |
| | }; |
| | |
| | |
| | __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; |
| | |
| | |
| | __webpack_require__.p = ""; |
| | |
| | |
| | |
| | return __webpack_require__(__webpack_require__.s = 5); |
| | }) |
| | |
| | ([ |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| |
|
| | const toString = Object.prototype.toString; |
| |
|
| | function isAnyArray(object) { |
| | return toString.call(object).endsWith('Array]'); |
| | } |
| |
|
| | module.exports = isAnyArray; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | Object.defineProperty(exports, "__esModule", { value: true }); |
| | var umap_1 = __webpack_require__(6); |
| | exports.UMAP = umap_1.UMAP; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, exports, __webpack_require__) { |
| |
|
| | "use strict"; |
| |
|
| |
|
| | var mlMatrix = __webpack_require__(9); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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]); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| |
|
| |
|
| | }), |
| | |
| | (function(module, __webpack_exports__, __webpack_require__) { |
| |
|
| | "use strict"; |
| | __webpack_require__.r(__webpack_exports__); |
| |
|
| | |
| | var src = __webpack_require__(0); |
| | var src_default = __webpack_require__.n(src); |
| |
|
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | 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; |
| | } |
| |
|
| | var lib_es6 = (lib_es6_max); |
| |
|
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | 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; |
| | } |
| |
|
| | var ml_array_min_lib_es6 = (lib_es6_min); |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | 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; |
| | } |
| |
|
| | var ml_array_rescale_lib_es6 = (rescale); |
| |
|
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get pivotPermutationVector() { |
| | return this.pivotVector.slice(); |
| | } |
| | } |
| |
|
| | |
| | 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; |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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(); |
| | |
| | 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; |
| | } |
| | |
| | } |
| | } |
| |
|
| | 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(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); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | solveForDiagonal(value) { |
| | return this.solve(matrix_Matrix.diag(value)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get condition() { |
| | return this.s[0] / this.s[Math.min(this.m, this.n) - 1]; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get norm2() { |
| | return this.s[0]; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get diagonal() { |
| | return this.s; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get threshold() { |
| | return Number.EPSILON / 2 * Math.max(this.m, this.n) * this.s[0]; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get leftSingularVectors() { |
| | if (!matrix_Matrix.isMatrix(this.U)) { |
| | this.U = new matrix_Matrix(this.U); |
| | } |
| | return this.U; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get rightSingularVectors() { |
| | if (!matrix_Matrix.isMatrix(this.V)) { |
| | this.V = new matrix_Matrix(this.V); |
| | } |
| | return this.V; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get diagonalMatrix() { |
| | return matrix_Matrix.diag(this.s); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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'); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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'); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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`); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| | 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; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | 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 |
| | ); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | 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] |
| | ); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | 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]); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | function AbstractMatrix(superCtor) { |
| | if (superCtor === undefined) superCtor = Object; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class Matrix extends superCtor { |
| | static get [Symbol.species]() { |
| | return this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static empty(rows, columns) { |
| | return new this(rows, columns); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static zeros(rows, columns) { |
| | return this.empty(rows, columns).fill(0); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static ones(rows, columns) { |
| | return this.empty(rows, columns).fill(1); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | static checkMatrix(value) { |
| | return Matrix.isMatrix(value) ? value : new this(value); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | static isMatrix(value) { |
| | return (value != null) && (value.klass === 'Matrix'); |
| | } |
| |
|
| | |
| | |
| | |
| | get size() { |
| | return this.rows * this.columns; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | isRowVector() { |
| | return this.rows === 1; |
| | } |
| |
|
| | |
| | |
| | |
| | isColumnVector() { |
| | return this.columns === 1; |
| | } |
| |
|
| | |
| | |
| | |
| | isVector() { |
| | return (this.rows === 1) || (this.columns === 1); |
| | } |
| |
|
| | |
| | |
| | |
| | isSquare() { |
| | return this.rows === this.columns; |
| | } |
| |
|
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | set(rowIndex, columnIndex, value) { |
| | throw new Error('set method is unimplemented'); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | get(rowIndex, columnIndex) { |
| | throw new Error('get method is unimplemented'); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | neg() { |
| | return this.mulS(-1); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | getRowVector(index) { |
| | return this.constructor.rowVector(this.getRow(index)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | getColumnVector(index) { |
| | return this.constructor.columnVector(this.getColumn(index)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | sum(by) { |
| | switch (by) { |
| | case 'row': |
| | return sumByRow(this); |
| | case 'column': |
| | return sumByColumn(this); |
| | default: |
| | return sumAll(this); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | mean() { |
| | return this.sum() / this.size; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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}`); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | mmul(other) { |
| | other = this.constructor.checkMatrix(other); |
| | if (this.columns !== other.rows) { |
| | |
| | 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); |
| |
|
| | |
| | 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); |
| |
|
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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) { |
| | |
| | console.warn(`Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.`); |
| | } |
| |
|
| | |
| | |
| | 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; |
| | } |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | var r = Math.max(r1, r2); |
| | var c = Math.max(c1, c2); |
| | x = embed(x, r, c); |
| | y = embed(y, r, c); |
| |
|
| | |
| | function blockMult(a, b, rows, cols) { |
| | |
| | if (rows <= 512 || cols <= 512) { |
| | return a.mmul(b); |
| | } |
| |
|
| | |
| | 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); |
| | |
| | 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); |
| |
|
| | |
| | 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); |
| |
|
| | |
| | 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); |
| |
|
| | |
| | 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); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | transposeView() { |
| | return new transpose_MatrixTransposeView(this); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | rowView(row) { |
| | checkRowIndex(this, row); |
| | return new row_MatrixRowView(this, row); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | columnView(column) { |
| | checkColumnIndex(this, column); |
| | return new column_MatrixColumnView(this, column); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | flipRowView() { |
| | return new flipRow_MatrixFlipRowView(this); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | flipColumnView() { |
| | return new flipColumn_MatrixFlipColumnView(this); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | subMatrixView(startRow, endRow, startColumn, endColumn) { |
| | return new sub_MatrixSubView(this, startRow, endRow, startColumn, endColumn); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | selectionView(rowIndices, columnIndices) { |
| | return new selection_MatrixSelectionView(this, rowIndices, columnIndices); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | rowSelectionView(rowIndices) { |
| | return new rowSelection_MatrixRowSelectionView(this, rowIndices); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | columnSelectionView(columnIndices) { |
| | return new columnSelection_MatrixColumnSelectionView(this, columnIndices); |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | det() { |
| | if (this.isSquare()) { |
| | var a, b, c, d; |
| | if (this.columns === 2) { |
| | |
| | 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) { |
| | |
| | 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 { |
| | |
| | return new lu_LuDecomposition(this).determinant; |
| | } |
| | } else { |
| | throw Error('Determinant can only be calculated for a square 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; |
| | } |
| | } |
| |
|
| | |
| | s = this.constructor[Symbol.species].diag(s); |
| | return V.mmul(s.mmul(U.transposeView())); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | 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; |
| |
|
| | |
| | |
| | |
| |
|
| | 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 = [ |
| | |
| | ['+', 'add'], |
| | ['-', 'sub', 'subtract'], |
| | ['*', 'mul', 'multiply'], |
| | ['/', 'div', 'divide'], |
| | ['%', 'mod', 'modulus'], |
| | |
| | ['&', 'and'], |
| | ['|', 'or'], |
| | ['^', 'xor'], |
| | ['<<', 'leftShift'], |
| | ['>>', 'signPropagatingRightShift'], |
| | ['>>>', 'rightShift', 'zeroFillRightShift'] |
| | ]; |
| |
|
| | var i; |
| | var eval2 = 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; |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| | 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) { |
| | |
| | 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)) { |
| | |
| | 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]; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| | class WrapperMatrix1D_WrapperMatrix1D extends AbstractMatrix() { |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| | class WrapperMatrix2D_WrapperMatrix2D extends AbstractMatrix() { |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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'); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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(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); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | isFullRank() { |
| | var columns = this.QR.columns; |
| | for (var i = 0; i < columns; i++) { |
| | if (this.Rdiag[i] === 0) { |
| | return false; |
| | } |
| | } |
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | 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)); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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); |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| |
|
| | |
| | function xrange(n, exception) { |
| | var range = []; |
| | for (var i = 0; i < n; i++) { |
| | if (i !== exception) { |
| | range.push(i); |
| | } |
| | } |
| | return range; |
| | } |
| |
|
| | |
| | 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(); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | 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; |
| | } |
| |
|
| | |
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get realEigenvalues() { |
| | return this.d; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get imaginaryEigenvalues() { |
| | return this.e; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get eigenvectorMatrix() { |
| | if (!matrix_Matrix.isMatrix(this.V)) { |
| | this.V = new matrix_Matrix(this.V); |
| | } |
| | return this.V; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | 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]; |
| | } |
| | } |
| |
|
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | get lowerTriangularMatrix() { |
| | return this.L; |
| | } |
| | } |
| |
|
| | |
| | __webpack_require__.d(__webpack_exports__, "default", function() { return matrix_Matrix; }); |
| | __webpack_require__.d(__webpack_exports__, "Matrix", function() { return matrix_Matrix; }); |
| | __webpack_require__.d(__webpack_exports__, "abstractMatrix", function() { return AbstractMatrix; }); |
| | __webpack_require__.d(__webpack_exports__, "wrap", function() { return wrap; }); |
| | __webpack_require__.d(__webpack_exports__, "WrapperMatrix2D", function() { return WrapperMatrix2D_WrapperMatrix2D; }); |
| | __webpack_require__.d(__webpack_exports__, "WrapperMatrix1D", function() { return WrapperMatrix1D_WrapperMatrix1D; }); |
| | __webpack_require__.d(__webpack_exports__, "solve", function() { return solve; }); |
| | __webpack_require__.d(__webpack_exports__, "inverse", function() { return inverse; }); |
| | __webpack_require__.d(__webpack_exports__, "linearDependencies", function() { return linearDependencies; }); |
| | __webpack_require__.d(__webpack_exports__, "SingularValueDecomposition", function() { return svd_SingularValueDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "SVD", function() { return svd_SingularValueDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "EigenvalueDecomposition", function() { return evd_EigenvalueDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "EVD", function() { return evd_EigenvalueDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "CholeskyDecomposition", function() { return cholesky_CholeskyDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "CHO", function() { return cholesky_CholeskyDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "LuDecomposition", function() { return lu_LuDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "LU", function() { return lu_LuDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "QrDecomposition", function() { return qr_QrDecomposition; }); |
| | __webpack_require__.d(__webpack_exports__, "QR", function() { return qr_QrDecomposition; }); |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | }) |
| | ]); |
| | }); |