// given a matrix of distances between some points, returns the /// point coordinates that best approximate the distances mds_classic = function(distances, dimensions) { dimensions = dimensions || 2; // square distances var M = numeric.mul(-.5, numeric.pow(distances, 2)); // double centre the rows/columns function mean(A) { return numeric.div(numeric.add.apply(null, A), A.length); } var rowMeans = mean(M), colMeans = mean(numeric.transpose(M)), totalMean = mean(rowMeans); for (var i = 0; i < M.length; ++i) { for (var j =0; j < M[0].length; ++j) { M[i][j] += totalMean - rowMeans[i] - colMeans[j]; } } // take the SVD of the double centred matrix, and return the // points from it var ret = numeric.svd(M), eigenValues = numeric.sqrt(ret.S); return ret.U.map(function(row) { return numeric.mul(row, eigenValues).splice(0, dimensions); }); };