void bespoke(char *treefile, char *leaffile, int burnin, int samples, int lag, char *outdir, int logging) {
	FILE *logfp;
	node_t *tree;
	mcmc_t mcmc;
	gslws_t ws;
	sampman_t sm;

	// Open log file
	if(logging) {
		logfp = fopen("logfile", "w");
	} else {
		logfp = fopen("/dev/null", "w");
	}

	initialise_mcmc(&mcmc);
	initialise_sampman(&sm, outdir);
	alloc_gslws(&ws);
	// Compute stability sampling rate
	sm.stability_sampling_rate = samples / 500.0;

	tree = build_tree(treefile, leaffile, 0, NULL);
	compute_single_tree_probabilities(&mcmc, tree, &ws);
	do_single_tree_inference(logfp, &mcmc, tree, &ws, &sm, burnin, samples, lag);
	free(tree);
	compute_means(&sm);
	save_indiv_q(outdir, &sm);
	fclose(logfp);
}
Exemple #2
0
int main(int argc, char *argv[])
{
    struct parms parms;		/* command line parms */
    struct files files;		/* file descriptors, io, buffers */
    struct Signature S;
    struct GModule *module;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("imagery"));
    G_add_keyword(_("classification"));
    G_add_keyword(_("supervised"));
    G_add_keyword(_("MLC"));
    module->description =
	_("Generates statistics for i.maxlik from raster map.");

    parse(argc, argv, &parms);
    openfiles(&parms, &files);
    read_training_labels(&parms, &files);

    get_training_classes(&files, &S);
    compute_means(&files, &S);
    compute_covariances(&files, &S);
    check_signatures(&S);
    write_sigfile(&parms, &S);

    G_done_msg(" ");
    
    exit(EXIT_SUCCESS);
}
void balanced_whole_shared_q(int method, int shuffle, int burnin, int samples, int lag, int treecount, char *outdir, int logging) {
	FILE *logfp;
	int treeindex, i;
	char methods[][16] = {"geographic", "genetic", "feature", "combination" };
	char filename[1024];
	node_t **trees = calloc(6, sizeof(node_t*));
	node_t **subtrees = calloc(6, sizeof(node_t*));
	mcmc_t mcmc;
	gslws_t *wses = calloc(6, sizeof(gslws_t));
	sampman_t *sms = calloc(6, sizeof(sampman_t));
	ubertree_t ut;

	// Open log file
	if(logging) {
		logfp = fopen("logfile", "w");
	} else {
		logfp = fopen("/dev/null", "w");
	}

	initialise_mcmc(&mcmc);
	initialise_ubertree(&ut);

	for(i=0; i<6; i++) {
		alloc_gslws(&wses[i]);
		initialise_sampman(&sms[i], outdir);
		sms[i].stability_sampling_rate = (treecount*samples) / 500;
	}

	// Loop over trees...
	for(treeindex=0; treeindex<treecount; treeindex++) {
		mcmc.dummy_tree_age = (55000+gsl_ran_gaussian(mcmc.r, 2500)) / 10000.0;
		/* Build tree(s) */
		for(i=0; i<6; i++) load_tree(&trees[i], "../TreeBuilder/generated_trees/whole/", method, i, treeindex, shuffle);
		for(i=0; i<6; i++) load_tree(&subtrees[i], "../TreeBuilder/generated_trees/whole/", method, i, treeindex, shuffle);
		/* Draw samples for this tree (set) */
		compute_balanced_multi_tree_probabilities(&mcmc, subtrees, wses);
		do_balanced_multi_tree_inference(logfp, &mcmc, subtrees, trees, wses, sms, &ut, burnin, samples, lag);
		/* Free up tree memory */
		for(i=0; i<6; i++) free(trees[i]);
	}

	// Finish up
	for(i=0; i<6; i++) compute_means(&sms[i]);
	sprintf(filename, "%s/%s/", outdir, methods[method]);
	save_common_q(filename, sms);
	save_ubertree(&ut, filename);
	fclose(logfp);
}
void whole_indiv_q(int method, int shuffle, int burnin, int samples, int lag, int treecount, char *outdir, int logging) {
	FILE *logfp;
	uint8_t family;
	int treeindex;
	char filename[1024];
	char families[][16] = {"afro", "austro", "indo", "niger", "nilo", "sino", "tng", "amer"};
	char types[][16] = {"geographic", "genetic", "feature", "combination" };
	node_t *tree;
	mcmc_t mcmc;
	gslws_t ws;
	sampman_t sm;

	// Open log file
	if(logging) {
		logfp = fopen("logfile", "w");
	} else {
		logfp = fopen("/dev/null", "w");
	}

	initialise_mcmc(&mcmc);
	initialise_sampman(&sm, outdir);
	alloc_gslws(&ws);
	// Compute stability sampling rate
	sm.stability_sampling_rate = (treecount*samples) / 500;

	// Loop over families
	for(family=0; family<NUM_TREES; family++) {
		reset_sampman(&sm);
		// Loop over trees
		for(treeindex=0; treeindex<treecount; treeindex++) {
			/* Build tree */
			load_tree(&tree, "../TreeBuilder/generated_trees/whole/", method, family, treeindex, shuffle);
			/* Draw samples for this tree (set) */
			compute_single_tree_probabilities(&mcmc, tree, &ws);
			do_single_tree_inference(logfp, &mcmc, tree, &ws, &sm, burnin, samples, lag);
			/* Free up tree memory */
			free(tree);
		}

		// Finish up
		compute_means(&sm);
		sprintf(filename, "%s/%s/%s/", outdir, types[method], families[family]);
		save_indiv_q(filename, &sm);
	}

	fclose(logfp);
}
Exemple #5
0
void
test_compute_means
(void)
{

   double mean;

   uint32_t x1[1] = {2595};
   compute_means(x1, 1, 1, &mean);
   test_assert(mean == 2595.0);

   uint32_t x2[7] = {0,0,0,1,1,2,5};
   compute_means(x2, 1, 7, &mean);
   test_assert(fabs(mean-1.28571428) < 1e-6);

   uint32_t x3[5] = {0,89,231,55,309};
   compute_means(x3, 1, 5, &mean);
   test_assert(fabs(mean-136.8) < 1e-6);

   // 0:112, 1:94, 2:28, 3:12, 4:3, 7:1
   uint32_t x4[250] = {0,0,0,3,0,0,1,1,1,1,1,2,0,2,0,0,1,0,0,0,1,1,0,1,
      1,0,1,1,0,2,1,0,2,1,1,0,2,1,1,1,1,1,0,0,2,0,2,1,1,1,2,1,0,0,
      1,0,1,0,0,1,0,0,3,2,0,0,0,0,0,2,1,1,1,0,0,1,0,0,1,0,0,1,0,1,
      0,1,2,1,2,1,0,0,0,2,0,0,0,1,2,1,0,1,1,1,2,0,0,0,0,0,2,1,3,0,
      2,3,0,0,0,1,0,0,1,1,0,0,0,0,1,0,0,1,0,3,1,0,0,0,1,1,0,0,0,0,
      0,1,0,0,0,0,1,2,1,0,2,4,0,1,0,1,0,1,0,1,1,1,0,1,1,1,1,0,0,1,
      0,1,1,3,1,1,1,1,0,0,0,0,3,1,3,0,1,1,0,0,0,1,1,0,1,2,4,2,0,0,
      4,0,2,1,0,0,2,1,2,1,7,1,2,3,0,0,1,1,0,3,1,1,1,3,1,1,0,0,0,0,
      1,2,2,0,1,1,0,1,1,1,0,2,3,0,0,0};
   compute_means(x4, 1, 250, &mean);
   test_assert(fabs(mean-0.82) < 1e-6);

   // Compute means in several dimensions.
   double means2[2];

   uint32_t x5[2] = {1,2595};
   compute_means(x5, 2, 1, means2);
   test_assert(means2[0] == 1.0);
   test_assert(means2[1] == 2595.0);

   uint32_t x6[4] = {1,2,11,12};
   compute_means(x6, 2, 2, means2);
   test_assert(means2[0] == 6.0);
   test_assert(means2[1] == 7.0);

   return;

}
Exemple #6
0
void
test_eval_nb_dfda
(void)
{

   // 0:14, 1:5, 2:4, 3:1, 5:1
   uint32_t x[25] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    1,1,1,1,1,2,2,2,2,3,5 };
   tab_t *tab = tabulate(x, 1, 25);
   double mean;
   compute_means(x, 1, 25, &mean);
   test_assert(fabs(eval_nb_dfda(1.0, tab)+1.41167874) < 1e-6);
   test_assert(fabs(eval_nb_dfda(1.2, tab)+0.58911102) < 1e-6);
   test_assert(fabs(eval_nb_dfda(1.3, tab)+0.36790287) < 1e-6);
   test_assert(fabs(eval_nb_dfda(1.4, tab)+0.21643981) < 1e-6);
   test_assert(fabs(eval_nb_dfda(1.5, tab)+0.11168877) < 1e-6);
   test_assert(fabs(eval_nb_dfda(2.0, tab)-0.08773865) < 1e-6);

   free(tab);

   return;

}
Exemple #7
0
/* Function kmeans.
 * Run kmeans clustering on a set of input descriptors.
 *
 * Inputs:
 *   n          : number of input descriptors
 *   dim        : dimension of each input descriptor
 *   k          : number of means to compute
 *   restarts   : number of random restarts to perform
 *   v          : array of pointers to dim-dimensional descriptors
 *
 * Output:
 *   means      : array of output means.  The means should be
 *                concatenated into one long array of length k*dim.
 *   clustering : assignment of descriptors to means (should
 *                range between 0 and k-1), stored as an array of
 *                length n.  clustering[i] contains the
 *                cluster ID for point i
 */
double kmeans(int n, int dim, int k, int restarts, unsigned char **v,
              double *means, unsigned int *clustering)
{
    int i;
    double min_error = DBL_MAX;

    double *means_curr, *means_new, *work;
    int *starts;
    unsigned int *clustering_curr;

    double changed_pct_threshold = 0.05; // 0.005;

    if (n <= k) {
        printf("[kmeans] Error: n <= k\n");
        return -1;
    }

    means_curr = (double *) malloc(sizeof(double) * dim * k);
    means_new = (double *) malloc(sizeof(double) * dim * k);
    clustering_curr = (unsigned int *) malloc(sizeof(unsigned int) * n);
    starts = (int *) malloc(sizeof(int) * k);
    work = (double *) malloc(sizeof(double) * dim);

    if (means_curr == NULL) {
        printf("[kmeans] Error allocating means_curr\n");
        exit(-1);
    }

    if (means_new == NULL) {
        printf("[kmeans] Error allocating means_new\n");
        exit(-1);
    }

    if (clustering_curr == NULL) {
        printf("[kmeans] Error allocating clustering_curr\n");
        exit(-1);
    }

    if (starts == NULL) {
        printf("[kmeans] Error allocating starts\n");
        exit(-1);
    }

    if (work == NULL) {
        printf("[kmeans] Error allocating work\n");
        exit(-1);
    }

    for (i = 0; i < restarts; i++) {
        int j;
        double max_change = 0.0;
        double error = 0.0;
        int round = 0;

        choose(n, k, starts);

        for (j = 0; j < k; j++) {
            fill_vector(means_curr + j * dim, v[starts[j]], dim);
        }

        /* Compute new assignments */
        timeval start, stop;
        gettimeofday(&start, NULL);

        int changed = 0;
        changed = compute_clustering_kd_tree(n, dim, k, v, means_curr,
                                             clustering_curr, error);

        double changed_pct = (double) changed / n;

        do {
            gettimeofday(&stop, NULL);

            long seconds  = stop.tv_sec  - start.tv_sec;
            long useconds = stop.tv_usec - start.tv_usec;
            double etime = seconds + useconds * 0.000001;

            printf("Round %d: changed: %d\n", i, changed);
            printf("Round took %0.3lfs\n", etime);
            fflush(stdout);

            gettimeofday(&start, NULL);

            /* Recompute means */
            max_change = compute_means(n, dim, k, v,
                                       clustering_curr, means_new);

            memcpy(means_curr, means_new, sizeof(double) * dim * k);

            /* Compute new assignments */
            changed = compute_clustering_kd_tree(n, dim, k, v, means_curr,
                                                 clustering_curr, error);

            changed_pct = (double) changed / n;

            round++;
        } while (changed_pct > changed_pct_threshold);

        max_change = compute_means(n, dim, k, v, clustering_curr, means_new);
        memcpy(means_curr, means_new, sizeof(double) * dim * k);

        if (error < min_error) {
            min_error = error;
            memcpy(means, means_curr, sizeof(double) * k * dim);
            memcpy(clustering, clustering_curr, sizeof(unsigned int) * n);
        }
    }


    free(means_curr);
    free(means_new);
    free(clustering_curr);
    free(starts);
    free(work);

    return compute_error(n, dim, k, v, means, clustering);
}
Exemple #8
0
void 
stereo_matching_zncc(
    float *image_l, 
    float *image_r, 
    double *score, 
    int width, 
    int height, 
    int wx, 
    int wy, 
    int disparity_min, 
    int disparity_max)
{
	unsigned int    x;
	int             i, j, y, left, right, wx2, wy2;
	float  *p_l, *p_r;
	float          pix_l, pix_r;
    float          *mean_l, *mean_r,
	               *pmean_l, *pmean_r;

	double          ncc, den;
	double          sum, sum_l, sum_r;
	int             disp, right_lim, left_lim, ndisp;

	mean_l = (float *) CALLOC(width * height, sizeof(double));
	mean_r = (float *) CALLOC(width * height, sizeof(double));
	compute_means(image_l, image_r, wx, wy, width, height, mean_l, mean_r);

    // following line to all sim metrics PIC
    ndisp = disparity_max - disparity_min + 1;
    if (ndisp < 0)
        ndisp = -ndisp;
    ndisp++;

	wx2 = (wx - 1) / 2;
	wy2 = (wy - 1) / 2;
	left = wx2;
	right = width - wx2;

	for (disp = disparity_min; disp < disparity_max; disp++) {

		for (y = wy2; y < (height-wy2); y++) {
			if (disp < 0) {
				p_l = image_l + y * width + wx2;
				p_r = image_r + y * width - disp + wx2;
				pmean_l = mean_l + y * width + wx2;
				pmean_r = mean_r + y * width - disp + wx2;
			}
			else {
				p_l = image_l + y * width + disp + wx2;
				p_r = image_r + y * width + wx2;
				pmean_l = mean_l + y * width + disp + wx2;
				pmean_r = mean_r + y * width + wx2;
			}

			right_lim = (disp < 0) ? right + disp : right;
			left_lim = (disp < 0) ? left : left + disp;

			for (x = left_lim; x < right_lim; x++) {

				sum = 0;
				sum_l = 0;
				sum_r = 0;

                /* inner matching loop */
				for (i = -wx2; i < wx2; i++) {      // x
					for (j = -wy2; j < wy2; j++) {  // y
						pix_l = REF(p_l, i,j) - *pmean_l;
						pix_r = REF(p_r, i,j) - *pmean_r;

						sum += pix_l * pix_r;
						sum_l += pix_l * pix_l;
						sum_r += pix_r * pix_r;
					}
                }

				den = sqrt(sum_l * sum_r);

				if (den != 0)
					ncc = sum / den;
				else
					ncc = INFINITY;

                // following line to all sim metrics PIC
                REF3(score, x,y,disp-disparity_min) = ncc;

				p_l++;
				p_r++;
				pmean_l++;
				pmean_r++;
			}	/* for x */
		}		/* for y */
	}			/* for disparity */

	mxFree(mean_l);
	mxFree(mean_r);
}				/* match_ZNCC_l */
void split_shared_q(int method, int shuffle, int burnin, int samples, int lag, int treecount, char *outdir, int logging) {
	FILE *logfp;
	FILE *correlfp;
	int treeindex, i, j, k;
	char filename[1024];
	char methods[][16] = {"geographic", "genetic", "feature", "combination" };
	node_t **trees1 = calloc(NUM_TREES, sizeof(node_t*));
	node_t **subtrees1 = calloc(NUM_TREES, sizeof(node_t*));
	node_t **trees2 = calloc(NUM_TREES, sizeof(node_t*));
	node_t **subtrees2 = calloc(NUM_TREES, sizeof(node_t*));
	mcmc_t mcmc1, mcmc2;
	gslws_t *wses1 = calloc(NUM_TREES, sizeof(gslws_t));
	gslws_t *wses2 = calloc(NUM_TREES, sizeof(gslws_t));
	sampman_t *sms1 = calloc(NUM_TREES, sizeof(sampman_t));
	sampman_t *sms2 = calloc(NUM_TREES, sizeof(sampman_t));
	gsl_matrix *q1 = gsl_matrix_alloc(6, 6);
	gsl_matrix *q2 = gsl_matrix_alloc(6, 6);
	double qcorrel1[6*NUM_TREES], qcorrel2[6*NUM_TREES];
	double anccorrel1[6*NUM_TREES], anccorrel2[6*NUM_TREES];
	double qcorrelation = 0;
	double anccorrelation = 0;

	// Open log file
	if(logging) {
		logfp = fopen("logfile", "w");
	} else {
		logfp = fopen("/dev/null", "w");
	}

	initialise_mcmc(&mcmc1);
	initialise_mcmc(&mcmc2);
	for(i=0; i<NUM_TREES; i++) {
		alloc_gslws(&wses1[i]);
		alloc_gslws(&wses2[i]);
		initialise_sampman(&sms1[i], outdir);
		initialise_sampman(&sms2[i], outdir);
		// Compute stability sampling rate
		sms1[i].stability_sampling_rate = (treecount*samples) / 500.0;
		sms2[i].stability_sampling_rate = (treecount*samples) / 500.0;
	}

	// Loop over trees...
	for(treeindex=0; treeindex<treecount; treeindex++) {

		/* Build tree(s) */
		for(i=0; i<NUM_TREES; i++) {
			load_tree(&trees1[i], "../TreeBuilder/generated_trees/split/1/", method, i, treeindex, shuffle);
			load_tree(&subtrees1[i], "../TreeBuilder/generated_trees/split/1/", method, i, treeindex, shuffle);
			load_tree(&trees2[i], "../TreeBuilder/generated_trees/split/2/", method, i, treeindex, shuffle);
			load_tree(&subtrees2[i], "../TreeBuilder/generated_trees/split/2/", method, i, treeindex, shuffle);
		}
		/* Draw samples for this tree (set) */
		compute_multi_tree_probabilities(&mcmc1, subtrees1, wses1);
		compute_multi_tree_probabilities(&mcmc2, subtrees2, wses2);

		/* Burn in */
		for(i=0; i<burnin; i++) {
			multi_tree_mcmc_iteration(logfp, &mcmc1, subtrees1, wses1);
			multi_tree_mcmc_iteration(logfp, &mcmc2, subtrees2, wses2);
		}

		gsl_matrix_set_zero(q1);
		gsl_matrix_set_zero(q2);
		memset(anccorrel1, 0, 6*NUM_TREES*sizeof(double));
		memset(anccorrel2, 0, 6*NUM_TREES*sizeof(double));
		/* Take samples */
		for(i=0; i<samples; i++) {
			if(gsl_rng_uniform_int(mcmc1.r, 10000) >= 9999) {
				/* Random restart! */
				random_restart(&mcmc1);
				random_restart(&mcmc2);
				compute_multi_tree_probabilities(&mcmc1, subtrees1, wses1);
				compute_multi_tree_probabilities(&mcmc2, subtrees2, wses2);
				for(j=0; j<burnin; j++) {
					multi_tree_mcmc_iteration(logfp, &mcmc1, subtrees1, wses1);
					multi_tree_mcmc_iteration(logfp, &mcmc2, subtrees2, wses2);
				}
			}

			for(j=0; j<lag; j++) {
				multi_tree_mcmc_iteration(logfp, &mcmc1, subtrees1, wses1);
				multi_tree_mcmc_iteration(logfp, &mcmc2, subtrees2, wses2);
			}

			build_q(&mcmc1);
			build_q(&mcmc2);

			for(j=0; j<NUM_TREES; j++) {
				upwards_belprop(logfp, trees1[j], mcmc1.Q, &wses1[j]);
				upwards_belprop(logfp, trees2[j], mcmc2.Q, &wses2[j]);
				process_sample(&sms1[j], &mcmc1, &wses1[j], trees1[j]);
				process_sample(&sms2[j], &mcmc2, &wses2[j], trees2[j]);

			}

			/* Combine Q samples for this tree pair */
			gsl_matrix_add(q1, mcmc1.Q);
			gsl_matrix_add(q2, mcmc2.Q);
			for(j=0; j<NUM_TREES; j++) {
				for(k=0; k<6; k++) {
					anccorrel1[j*6+k] += trees1[j]->dist[k];
					anccorrel2[j*6+k] += trees2[j]->dist[k];
				}
			}


		}
		
		gsl_matrix_scale(q1, 1.0 / samples);
		gsl_matrix_scale(q2, 1.0 / samples);
		for(i=0; i<NUM_TREES; i++) {
			for(j=0; j<6; j++) {
				qcorrel1[i*6+j] = gsl_matrix_get(q1, i, j);
				qcorrel2[i*6+j] = gsl_matrix_get(q2, i, j);
				anccorrel1[i*6+j] /= (1.0*samples);
				anccorrel2[i*6+j] /= (1.0*samples);
			}
		}
		qcorrelation += gsl_stats_correlation(qcorrel1, 1, qcorrel2, 1, 36);
		anccorrelation += gsl_stats_correlation(anccorrel1, 1, anccorrel2, 1, 36);

		/***************************************************/
		/* Free up tree memory */
		for(i=0; i<NUM_TREES; i++) {
			free(trees1[i]);
			free(subtrees1[i]);
			free(trees2[i]);
			free(subtrees2[i]);
		}
	}
	qcorrelation /= treecount;
	anccorrelation /= treecount;

	// Finish up
	for(i=0; i<NUM_TREES; i++) {
		compute_means(&sms1[i]);
		compute_means(&sms2[i]);
	}
	sprintf(filename, "%s/%s/", outdir, methods[method]);
	strcat(filename, "/left-half/");
	save_common_q(filename, sms1);
	sprintf(filename, "%s/%s/", outdir, methods[method]);
	strcat(filename, "/right-half/");
	save_common_q(filename, sms2);

	sprintf(filename, "%s/%s/correlations", outdir, methods[method]);
	correlfp = fopen(filename, "w");
	fprintf(correlfp, "Q: %f\n", qcorrelation);
	fprintf(correlfp, "Anc: %f\n", anccorrelation);
	fclose(correlfp);

	fclose(logfp);
}
double HDP_MEDOIDS (vector<Instance*>& data, vector< vector<double> >& means, Lookups* tables, vector<double> lambdas, dist_func df, int FIX_DIM) {
    // STEP ZERO: validate input and initialization
    int N = tables->nWords;
    int D = tables->nDocs;
    vector< pair<int, int> > doc_lookup = *(tables->doc_lookup);
    double lambda_global = lambdas[0];
    double lambda_local = lambdas[1];

    vector< vector<double> > global_means (1, vector<double>(FIX_DIM, 0.0));
    vector< vector<int> > k (D, vector<int>(1,0));  // global association
    vector<int> z (N, 0); // local assignment
    vector<int> global_asgn (N, 0); // global assignment

    // STEP ONE: a. set initial *global* medoid as global mean
    compute_assignment (global_asgn, k, z, tables);
    compute_means (data, global_asgn, FIX_DIM, global_means);

    double last_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM);
    double new_cost = last_cost;
    while (true) {
        // 4. for each point x_ij,
        for (int j = 0; j < D; j ++) {
            for (int i = doc_lookup[j].first; i < doc_lookup[j].second; i++) {
                int num_global_means = global_means.size();
                vector<double> d_ij (num_global_means, 0.0);
                for (int p = 0; p < num_global_means; p ++) {
                    Instance* temp_ins = vec2ins(global_means[p]);
                    double euc_dist = df(data[i], temp_ins, FIX_DIM);
                    d_ij[p] = euc_dist * euc_dist;
                    delete temp_ins;
                }
                set<int> temp;
                for (int p = 0; p < num_global_means; p ++) temp.insert(p);
                int num_local_means = k[j].size();
                for (int q = 0; q < num_local_means; q ++) temp.erase(k[j][q]);
                set<int>::iterator it; 
                for (it=temp.begin(); it!=temp.end();++it) d_ij[*it] += lambda_local;
                int min_p = -1; double min_dij = INF;
                for (int p = 0; p < num_global_means; p ++) 
                    if (d_ij[p] < min_dij) {
                        min_p = p;
                        min_dij = d_ij[p];
                    }
                if (min_dij > lambda_global + lambda_local) {
                    z[i] = num_local_means; 
                    k[j].push_back(num_global_means);
                    vector<double> new_g(FIX_DIM, 0.0);
                    for (int f = 0; f < data[i]->fea.size(); f++)
                        new_g[data[i]->fea[f].first-1] = data[i]->fea[f].second;
                    global_means.push_back(new_g);
                    // cout << "global and local increment" << endl;
                } else {
                    bool c_exist = false;
                    for (int c = 0; c < num_local_means; c ++) 
                        if (k[j][c] == min_p) {
                            z[i] = c;
                            c_exist = true;
                            break;
                        }
                    if (!c_exist) {
                        z[i] = num_local_means;
                        k[j].push_back(min_p);
                       // cout << "local increment" << endl;
                    }
                }
            }
        }
        /*
        cout << "half..........." << endl;
        cout << "#global created: " << global_means.size() 
            << ", #global used: " << get_num_global_means(k);
            */
        new_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM);
        // 5. for all local clusters,
        for (int j = 0; j < D; j ++) {
            int begin_i = doc_lookup[j].first;
            int end_i = doc_lookup[j].second;
            int doc_len = doc_lookup[j].second - doc_lookup[j].first;
            int num_local_means = k[j].size();

            // all local clusters are distinct to each other
            /*
            set<int> temp;
            for (int y = 0; y < num_local_means; y++)
                temp.insert(k[j][y]);
            cout << temp.size() << " ==? " << num_local_means << endl;
            assert (temp.size() == num_local_means);
            */

            // compute means of local clusters
            vector< vector<double> > local_means (num_local_means, vector<double>(FIX_DIM, 0.0));
            vector<int> local_asgn (z.begin()+begin_i, z.begin()+end_i);
            vector<Instance*> local_data (data.begin()+begin_i,data.begin()+end_i);
            compute_means (local_data, local_asgn, FIX_DIM, local_means);
            assert (num_local_means == local_means.size());

            // pre-compute instances for global means 
            int num_global_means = global_means.size();
            vector<Instance*> temp_global_means (num_global_means, NULL);
            for (int p = 0; p < num_global_means; p ++) 
                temp_global_means[p] = vec2ins (global_means[p]);

            // pre-compute instances for local means 
            vector<Instance*> temp_local_means (num_local_means, NULL);
            for (int c = 0; c < num_local_means; c ++) 
                temp_local_means[c] = vec2ins (local_means[c]);

            for (int c = 0; c < num_local_means; c++) {
                // compute distance of local clusters to each global cluster
                num_global_means = global_means.size();
                vector<double> d_jcp (num_global_means, 0.0);
                double sum_d_ijc = 0.0; 
                for (int i = doc_lookup[j].first; i < doc_lookup[j].second; i ++) {
                    if (z[i] != c) continue;
                    double local_dist = df (data[i], temp_local_means[c], FIX_DIM);
                    sum_d_ijc += local_dist * local_dist;
                    for (int p = 0; p < num_global_means; p ++) {
                        double dist = df (data[i], temp_global_means[p], FIX_DIM);
                        d_jcp[p] += dist * dist;
                    }
                }
                int min_p = -1; double min_d_jcp = INF;
                for (int p = 0; p < num_global_means; p ++) 
                    if (d_jcp[p] < min_d_jcp) {
                        min_p = p;
                        min_d_jcp = d_jcp[p];
                    }
                assert (min_p >= 0);
                // cout << min_d_jcp << " " << lambda_global << " " << sum_d_ijc << endl;
                if (min_d_jcp > lambda_global + sum_d_ijc) {
                    global_means.push_back(local_means[c]); //  push mu_jc
                    temp_global_means.push_back(vec2ins (local_means[c]));
                    k[j][c] = num_global_means;
                    // cout << "global increment" << endl;
                } else {
                    k[j][c] = min_p;
                }
            }
            for (int c = 0; c < num_local_means; c ++) 
                delete temp_local_means[c];
            num_global_means = global_means.size();
            for (int p = 0; p < num_global_means; p ++) 
                delete temp_global_means[p];
        }
        // 6. for each global clusters,
        compute_assignment (global_asgn, k, z, tables);
        /*
        cout << "compute global means.." << endl;
        cout << "#global created: " << global_means.size() 
            << ", #global used: " << get_num_global_means(k);
            */
        compute_means (data, global_asgn, FIX_DIM, global_means);

        // 7. convergence?
        new_cost = compute_cost (data, global_means, k, z, lambdas, tables, df, FIX_DIM);
        if ( new_cost < objmin ) objmin = new_cost;
        objmin_trace << omp_get_wtime()-start_time << " " << objmin << endl;
        if (new_cost == last_cost)
            break;
        if (new_cost < last_cost) {
            last_cost = new_cost;
        } else {
            cerr << "failure" << endl;
            return INF;
            assert(false);    
        }
    }
    means = global_means;
    return last_cost;
}// entry main function