void kmClusEllipsoids( // clustered around ellipsoids KMpointArray pa, // point array (modified) int n, // number of points int dim, // dimension int n_col, // number of colors bool new_clust, // generate new clusters. double std_dev_small, // small standard deviation double std_dev_lo, // low standard deviation for ellipses double std_dev_hi, // high standard deviation for ellipses int max_dim) // maximum dimension of the flats { static KMpointArray clusters = NULL; // cluster centers static KMpointArray stdDev = NULL; // standard deviations if (clusters == NULL || new_clust) { // need new cluster centers if (clusters != NULL) // clusters already exist kmDeallocPts(clusters); // get rid of them if (stdDev != NULL) // std deviations already exist kmDeallocPts(stdDev); // get rid of them clusters = kmAllocPts(n_col, dim); // alloc new clusters and devs stdDev = kmAllocPts(n_col, dim); for (int i = 0; i < n_col; i++) { // gen cluster center coords for (int d = 0; d < dim; d++) { clusters[i][d] = (KMcoord) kmRanUnif(-1,1); } } for (int c = 0; c < n_col; c++) { // generate cluster std dev int n_dim = 1 + kmRanInt(max_dim); // number of dimensions in flat for (int d = 0; d < dim; d++) { // generate std dev's // prob. of picking next dim double Prob = ((double) n_dim)/((double) (dim-d)); if (kmRan0() < Prob) { // add this one to ellipse // generate random std dev stdDev[c][d] = kmRanUnif(std_dev_lo, std_dev_hi); n_dim--; // one fewer dim to fill } else { // don't take this one stdDev[c][d] = std_dev_small;// use small std dev } } } } int next = 0; // next slot to fill for (int c = 0; c < n_col; c++) { // generate clusters int pick = (n+c)/n_col; // number of points to pick for (int i = 0; i < pick; i++) { for (int d = 0; d < dim; d++) { pa[next][d] = (KMcoord) (stdDev[c][d]*kmRanGauss() + clusters[c][d]); } next++; } } }
// assignment operator KMfilterCenters& KMfilterCenters::operator=(const KMfilterCenters& s) { if (this != &s) { // avoid self copy (x=x) // different sizes? if (kCtrs != s.kCtrs || getDim() != s.getDim()) { kmDeallocPts(sums); // deallocate old storage delete [] sumSqs; delete [] weights; delete [] dists; // allocate new storage sums = kmAllocPts(s.kCtrs, s.getDim()); sumSqs = new double[s.kCtrs]; weights = new int[s.kCtrs]; dists = new double[s.kCtrs]; } KMcenters& base = *this; base.operator=(s); // copy base class // copy array contents kmCopyPts(kCtrs, getDim(), s.sums, sums); kmCopy(kCtrs, s.sumSqs, sumSqs); kmCopy(kCtrs, s.weights, weights); kmCopy(kCtrs, s.dists, dists); valid = s.valid; } currDist = s.currDist; dampFactor = s.dampFactor; return *this; }
void KMdata::resize(int d, int n) { // resize point array if (d != dim || n != nPts) { // size change? dim = d; nPts = n; kmDeallocPts(pts); // deallocate old points pts = kmAllocPts(nPts, dim); } if (kcTree != NULL) { // kc-tree exists? delete kcTree; // deallocate kc-tree kcTree = NULL; } }
// assignment operator KMcenters& KMcenters::operator=(const KMcenters& s) { if (this != &s) { // avoid self assignment (x=x) // size change? if (kCtrs != s.kCtrs || getDim() != s.getDim()) { kmDeallocPts(ctrs); // reallocate points ctrs = kmAllocPts(s.kCtrs, s.getDim()); } kCtrs = s.kCtrs; pts = s.pts; kmCopyPts(kCtrs, s.getDim(), s.ctrs, ctrs); } return *this; }
KMpointArray kmAllocCopyPts( // allocate and copy point array int n, // number of points int dim, // dimension const KMpointArray source) // source point { KMpointArray dest = kmAllocPts(n, dim); for (int j = 0; j < n; j++) { for (int i = 0; i < dim; i++) { dest[j][i] = source[j][i]; } } return dest; }
void kmClusOrthFlats( // clustered along orthogonal flats KMpointArray pa, // point array (modified) int n, // number of points int dim, // dimension int n_col, // number of colors bool new_clust, // generate new clusters. double std_dev, // standard deviation within clusters int max_dim) // maximum dimension of the flats { const double CO_FLAG = 999; // special flag value static KMpointArray control = NULL; // control vectors if (control == NULL || new_clust) { // need new cluster centers if (control != NULL) { // clusters already exist kmDeallocPts(control); // get rid of them } control = kmAllocPts(n_col, dim); for (int c = 0; c < n_col; c++) { // generate clusters int n_dim = 1 + kmRanInt(max_dim); // number of dimensions in flat for (int d = 0; d < dim; d++) { // generate side locations // prob. of picking next dim double Prob = ((double) n_dim)/((double) (dim-d)); if (kmRan0() < Prob) { // add this one to flat control[c][d] = CO_FLAG; // flag this entry n_dim--; // one fewer dim to fill } else { // don't take this one control[c][d] = kmRanUnif(-1,1);// random value in [-1,1] } } } } int next = 0; // next slot to fill for (int c = 0; c < n_col; c++) { // generate clusters int pick = (n+c)/n_col; // number of points to pick for (int i = 0; i < pick; i++) { for (int d = 0; d < dim; d++) { if (control[c][d] == CO_FLAG) // dimension on flat pa[next][d] = (KMcoord) kmRanUnif(-1,1); else // dimension off flat pa[next][d] = (KMcoord) (std_dev*kmRanGauss() + control[c][d]); } next++; } } }
// standard constructor KMfilterCenters::KMfilterCenters(int k, KMdata& p, double df) : KMcenters(k, p) { if (p.getKcTree() == NULL) { // kc-tree not yet built? kmError("Building kc-tree", KMwarn); p.buildKcTree(); // build it now } sums = kmAllocPts(kCtrs, getDim()); sumSqs = new double[kCtrs]; weights = new int[kCtrs]; dists = new double[kCtrs]; currDist = KM_HUGE; dampFactor = df; currDBIndex = KM_HUGE; currXBIndex = KM_HUGE; invalidate(); // distortions are initially invalid }
void kmClusGaussPts( // clustered-Gaussian distribution KMpointArray pa, // point array (modified) int n, // number of points int dim, // dimension int n_col, // number of colors bool new_clust, // generate new clusters. double std_dev, // standard deviation within clusters double* clus_sep) // cluster separation (returned) { if (cgClusters == NULL || new_clust) {// need new cluster centers if (cgClusters != NULL) // clusters already exist kmDeallocPts(cgClusters); // get rid of them cgClusters = kmAllocPts(n_col, dim); // generate cluster center coords for (int i = 0; i < n_col; i++) { for (int d = 0; d < dim; d++) { cgClusters[i][d] = (KMcoord) kmRanUnif(-1,1); } } } double minDist = double(dim); // minimum inter-center sq'd distance for (int i = 0; i < n_col; i++) { // compute minimum separation for (int j = i+1; j < n_col; j++) { double dist = kmDist(dim, cgClusters[i], cgClusters[j]); if (dist < minDist) minDist = dist; } } // cluster separation if (clus_sep != NULL) *clus_sep = sqrt(minDist)/(sqrt(double(dim))*std_dev); for (int i = 0; i < n; i++) { int c = kmRanInt(n_col); // generate cluster index for (int d = 0; d < dim; d++) { pa[i][d] = (KMcoord) (std_dev*kmRanGauss() + cgClusters[c][d]); } } }
void KMcenters::resize(int k) { // resize array (if needed) if (k == kCtrs) return; kCtrs = k; kmDeallocPts(ctrs); ctrs = kmAllocPts(kCtrs, pts->getDim()); }
// standard constructor KMcenters::KMcenters(int k, KMdata& p) : kCtrs(k), pts(&p) { ctrs = kmAllocPts(kCtrs, p.getDim()); }
// standard constructor KMdata::KMdata(int d, int n) : dim(d), maxPts(n), nPts(n) { pts = kmAllocPts(n, d); kcTree = NULL; }