UNPKG

spectral-clustering-js

Version:
98 lines (97 loc) 4.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Utils_1 = require("./Utils"); var ml_matrix_1 = require("ml-matrix"); var Kmeans1D_1 = require("./Kmeans1D"); /** * Class dedicated to spectral clustering : * * compute the eigen values * * sort the eigen vectors accorting to the eigen values * * focus on the 2nd eiven vector (Fiedler's) * * run a k-means to cluster the components of the Fiedler's vector */ var SpectralClustering = /** @class */ (function () { function SpectralClustering(graph) { this.graph = graph; } SpectralClustering.prototype.compute = function (options) { if (options === void 0) { options = new Map(); } var defaultOptions = new Map([ ["laplacianMatrix", "connected"], ["requestedNbClusters", -1], ["maxClusters", 8] ]); var runningOptions = Utils_1.Utils.resolveRunningParameters(defaultOptions, options); var laplacianMatrix = null; if (runningOptions.get("laplacianMatrix") == "connected") { laplacianMatrix = this.extractStrictLaplacianMatrix(); } else { laplacianMatrix = this.extractDistanceLaplacianMatrix(); } var eigen = new ml_matrix_1.EigenvalueDecomposition(laplacianMatrix, { assumeSymmetric: true }); var nodes = this.graph.getNodes(); // the eigen vectors & values are already sorted // there is not need to do it again var fiedlerVector = eigen.eigenvectorMatrix.getColumn(1); // k-means to divide the FiedlerVector var kmeanCluster = new Kmeans1D_1.Kmeans1D(fiedlerVector); // is the number of clusters already known ? var requestedNbClusters = (runningOptions.get("requestedNbClusters")); var clusterResult = null; if (requestedNbClusters == -1) { clusterResult = kmeanCluster.findBestClustering((runningOptions.get("maxClusters"))); } else { // the methods returns [clusters, centroids], let's keep the clusters only clusterResult = kmeanCluster.tryToCluster(requestedNbClusters)[0]; } for (var i = 0; i < fiedlerVector.length; i++) { var nodeI = nodes[i]; nodeI.setCluster(clusterResult[i]); } }; SpectralClustering.prototype.extractStrictLaplacianMatrix = function () { var result = new ml_matrix_1.Matrix(this.graph.getNodes().length, this.graph.getNodes().length); var nodes = this.graph.getNodes(); for (var i = 0; i < nodes.length; i++) { var nodeI = nodes[i]; var connected = nodeI.getConnectedNodes(); for (var j = 0; j < nodes.length; j++) { var nodeJ = nodes[j]; if (nodeI.isConnectedTo(nodeJ)) { result.set(i, j, -1); } } result.set(i, i, connected.size); } return result; }; /** * Build a matrix showing the distance of nodes */ SpectralClustering.prototype.extractDistanceLaplacianMatrix = function () { var result = new ml_matrix_1.Matrix(this.graph.getNodes().length, this.graph.getNodes().length); var nodes = this.graph.getNodes(); for (var i = 0; i < nodes.length; i++) { var nodeI = nodes[i]; var sumDistances = 0; for (var j = 0; j < nodes.length; j++) { if (i != j) { var nodeJ = nodes[j]; if (nodeI.isConnectedTo(nodeJ)) { var distance = nodeI.getPoint().euclieanDistanceTo(nodeJ.getPoint()); //let distanceInLaplacian = 1/distance; var distanceInLaplacian = 1 / Math.log10(distance); result.set(i, j, -distanceInLaplacian); sumDistances += distanceInLaplacian; } } } result.set(i, i, sumDistances); } return result; }; return SpectralClustering; }()); exports.SpectralClustering = SpectralClustering;