static double kmRanGauss() { static int iset=0; static double gset; if (iset == 0) { // we don't have a deviate handy double v1, v2; double r = 2.0; while (r >= 1.0) { //------------------------------------------------------------ // Pick two uniform numbers in the square extending from -1 to // +1 in each direction, see if they are in the circle of radius // 1. If not, try again //------------------------------------------------------------ v1 = kmRanUnif(-1, 1); v2 = kmRanUnif(-1, 1); r = v1 * v1 + v2 * v2; } double fac = sqrt(-2.0 * log(r) / r); //----------------------------------------------------------------- // Now make the Box-Muller transformation to get two normal // deviates. Return one and save the other for next time. //----------------------------------------------------------------- gset = v1 * fac; iset = 1; // set flag return v2 * fac; } else { // we have an extra deviate handy iset = 0; // so unset the flag return gset; // and return it } }
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++; } } }
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++; } } }
void kmUniformPts( // uniform distribution KMpointArray pa, // point array (modified) int n, // number of points int dim) // dimension { for (int i = 0; i < n; i++) { for (int d = 0; d < dim; d++) { pa[i][d] = (KMcoord) (kmRanUnif(-1,1)); } } }
void kmMultiClus( // multi-sized clusters KMpointArray pa, // point array (modified) int n, // number of points int dim, // dimension int &k, // number of clusters (returned) double base_dev) // base standard deviation { int next = 0; // next point in array int nSamp = 0; // number of points sampled k = 0; // number of clusters generated KMpoint clusCenter = kmAllocPt(dim); // allocate center storage while (nSamp < n) { // until we have sampled enough int remain = n - nSamp; // number remaining to sample int clusSize = 2; // repeatedly double cluster size // with prob 1/2 while ((clusSize < remain) && (kmRan0() < 0.5)) clusSize *= 2; // don't exceed upper limit if (clusSize > remain) clusSize = remain; // generate center uniformly for (int d = 0; d < dim; d++) { clusCenter[d] = (KMcoord) kmRanUnif(-1,1); } // desired std dev for cluster double stdDev = base_dev*sqrt(1.0/clusSize); // generate cluster points for (int i = 0; i < clusSize; i++) { for (int d = 0; d < dim; d++) { pa[next][d] = (KMcoord) (stdDev*kmRanGauss()+clusCenter[d]); } next++; } nSamp += clusSize; // update number sampled k++; // one more cluster } kmDeallocPt(clusCenter); }
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]); } } }
// sample uniformly void KMorthRect::sample(int dim, KMpoint p) { for (int i = 0; i < dim; i++) p[i] = kmRanUnif(lo[i], hi[i]); }