/** * Performs clustering using pairwise average linking on the given distance * matrix. * * @return array of nodes. Each node object contains a left, right, and * distance. */ morpheus.AverageLinkage = function(nelements, distmatrix) { var j; var n; var clusterid; var number; var result; clusterid = []; // nelements; number = []; // nelements; result = []; // nelements - 1; for (var i = 0; i < nelements - 1; i++) { result[i] = { left : 0, right : 0, distance : 0 }; } /* * Setup a list specifying to which cluster an element belongs, and keep * track of the number of elements in each cluster (needed to calculate the * average). */ for (j = 0; j < nelements; j++) { number[j] = 1; clusterid[j] = j; } // ip, jp, and distance; var r = {}; // result array contains array of int left, int right, float distance; for (n = nelements; n > 1; n--) { morpheus.HCluster.findClosestPair(n, distmatrix, r); result[nelements - n] = {}; result[nelements - n].distance = r.distance; var is = r.ip; var js = r.jp; /* Save result */ result[nelements - n].left = clusterid[is]; result[nelements - n].right = clusterid[js]; /* Fix the distances */ var sum = number[is] + number[js]; for (j = 0; j < js; j++) { distmatrix[js][j] = distmatrix[is][j] * number[is] + distmatrix[js][j] * number[js]; distmatrix[js][j] /= sum; } for (j = js + 1; j < is; j++) { distmatrix[j][js] = distmatrix[is][j] * number[is] + distmatrix[j][js] * number[js]; distmatrix[j][js] /= sum; } for (j = is + 1; j < n; j++) { distmatrix[j][js] = distmatrix[j][is] * number[is] + distmatrix[j][js] * number[js]; distmatrix[j][js] /= sum; } for (j = 0; j < is; j++) distmatrix[is][j] = distmatrix[n - 1][j]; for (j = is + 1; j < n - 1; j++) distmatrix[j][is] = distmatrix[n - 1][j]; /* Update number of elements in the clusters */ number[js] = sum; number[is] = number[n - 1]; /* Update clusterids */ clusterid[js] = n - nelements - 1; clusterid[is] = clusterid[n - 1]; } return result; };