src/kmeans.cpp
// Could add early termination when dist exceeds min dist
Could add early termination when dist exceeds min dist
Could add early termination when dist exceeds min dist
unsigned int KMeansThread::Nearest(unsigned int o, float *obj,
				   double *ret_min_dist) {
  unsigned int best_c = assignments_[o];
  if (best_c == kMaxUInt) {
    unsigned int c;
    for (c = 0; c < num_clusters_; ++c) {
      if (cluster_sizes_[c] > 0) {
	best_c = c;
	break;
      }
    }
    if (c == num_clusters_) {
      fprintf(stderr, "No clusters with non-zero size?!?\n");
      exit(-1);
    }
  }
  float orig_min_dist = 0;
  for (unsigned int d = 0; d < dim_; ++d) {
    float ov = obj[d];
    float cm = means_[best_c][d];
    float dim_delta = ov - cm;
    orig_min_dist += dim_delta * dim_delta;
  }
  orig_min_dist = sqrt(orig_min_dist);
  float min_dist = orig_min_dist;
  unsigned char *neighbors = nearest_centroids_[best_c];
  while (true) {
    unsigned int c = *(unsigned int *)neighbors;
    if (c == kMaxUInt) break;
    if (c == best_c) continue;
    if (cluster_sizes_[c] == 0) continue;
    neighbors += sizeof(unsigned int);
    float centroid_dist = *(float *)neighbors;
    neighbors += sizeof(float);
    if (centroid_dist >= 2 * orig_min_dist) {
      continue;
    }
    float *cluster_means = means_[c];
    float dist_sq = 0;
    for (unsigned int d = 0; d < dim_; ++d) {
      float ov = obj[d];
      float cm = cluster_means[d];
      float dim_delta = ov - cm;
      dist_sq += dim_delta * dim_delta;
    }
    float dist = sqrt(dist_sq);
    if (dist < min_dist) {
      best_c = c;
      min_dist = dist;
    }
  }
  *ret_min_dist = min_dist;
  return best_c;
}
unsigned int KMeansThread :: Nearest ( unsigned int o , float * obj , double * ret_min_dist ) { unsigned int best_c = assignments_ [ o ] ; if ( best_c == kMaxUInt ) { unsigned int c ; for ( c = 0 ; c < num_clusters_ ; ++ c ) { if ( cluster_sizes_ [ c ] > 0 ) { best_c = c ; break ; } } if ( c == num_clusters_ ) { fprintf ( stderr , " \n " ) ; exit ( -1 ) ; } } float orig_min_dist = 0 ; for ( unsigned int d = 0 ; d < dim_ ; ++ d ) { float ov = obj [ d ] ; float cm = means_ [ best_c ] [ d ] ; float dim_delta = ov - cm ; orig_min_dist += dim_delta * dim_delta ; } orig_min_dist = sqrt ( orig_min_dist ) ; float min_dist = orig_min_dist ; unsigned char * neighbors = nearest_centroids_ [ best_c ] ; while ( true ) { unsigned int c = * ( unsigned int * ) neighbors ; if ( c == kMaxUInt ) break ; if ( c == best_c ) continue ; if ( cluster_sizes_ [ c ] == 0 ) continue ; neighbors += sizeof ( unsigned int ) ; float centroid_dist = * ( float * ) neighbors ; neighbors += sizeof ( float ) ; if ( centroid_dist >= 2 * orig_min_dist ) { continue ; } float * cluster_means = means_ [ c ] ; float dist_sq = 0 ; for ( unsigned int d = 0 ; d < dim_ ; ++ d ) { float ov = obj [ d ] ; float cm = cluster_means [ d ] ; float dim_delta = ov - cm ; dist_sq += dim_delta * dim_delta ; } float dist = sqrt ( dist_sq ) ; if ( dist < min_dist ) { best_c = c ; min_dist = dist ; } } * ret_min_dist = min_dist ; return best_c ; }
Could add early termination when dist exceeds min dist
Could add early termination when dist exceeds min dist
// Initialize best_c to the current assignment.  This will make the triangle // inequality based optimization work better. // Arbitrarily set best_c to first cluster with non-zero size