boolean centroidSearchBailOut = false; int i; int centroidCount = 0; for (i = 0; i < m_NumClusters; i++) { do { instIndex = RandomO.nextInt(tempInst.numInstances()); hk = new DecisionTable.hashKey(tempInst.instance(instIndex), tempInst.numAttributes()); if (initC.containsKey(hk)) { centroidCount++; } } while (initC.containsKey(hk) && centroidCount < instances.numInstances());
  public void buildClusterer(Instances data) throws Exception {    m_Iterations = 0;    if (data.checkForStringAttributes()) {      throw  new Exception("Can't handle string attributes!");    }    m_ReplaceMissingFilter = new ReplaceMissingValues();    m_ReplaceMissingFilter.setInputFormat(data);    Instances instances = Filter.useFilter(data, m_ReplaceMissingFilter);    m_Min = new double [instances.numAttributes()];    m_Max = new double [instances.numAttributes()];    for (int i = 0; i < instances.numAttributes(); i++) {      m_Min[i] = m_Max[i] = Double.NaN;    }        m_ClusterCentroids = new Instances(instances, m_NumClusters);    int[] clusterAssignments = new int [instances.numInstances()];    for (int i = 0; i < instances.numInstances(); i++) {      updateMinMax(instances.instance(i));    }    Instances tempInst = new Instances(instances);    Random RandomO = new Random(m_Seed);    int instIndex;    HashMap initC = new HashMap();    DecisionTable.hashKey hk = null;    boolean centroidSearchBailOut = false;    int i;    int centroidCount = 0;    for (i = 0; i < m_NumClusters; i++) {      do {	instIndex = RandomO.nextInt(tempInst.numInstances());	hk = new DecisionTable.hashKey(tempInst.instance(instIndex), 				       tempInst.numAttributes());	if (initC.containsKey(hk)) {	  centroidCount++;	}      } while (initC.containsKey(hk) && 	       centroidCount < instances.numInstances());      if (centroidCount >= instances.numInstances()) {	// bail out and set the number of requested clusters to i	centroidSearchBailOut = true;	break;      }      m_ClusterCentroids.add(tempInst.instance(instIndex));      initC.put(hk, null);      centroidCount++;    }    if (centroidSearchBailOut) {      m_NumClusters = i;    }    tempInst = null;    boolean converged = false;    int emptyClusterCount;    Instances [] tempI = new Instances[m_NumClusters];    m_squaredErrors = new double [m_NumClusters];    m_ClusterNominalCounts = new int [m_NumClusters][instances.numAttributes()][0];    while (!converged) {      emptyClusterCount = 0;      m_Iterations++;      converged = true;      for (i = 0; i < instances.numInstances(); i++) {	Instance toCluster = instances.instance(i);	int newC = clusterProcessedInstance(toCluster);	if (newC != clusterAssignments[i]) {	  converged = false;	}	clusterAssignments[i] = newC;      }            // update centroids      m_ClusterCentroids = new Instances(instances, m_NumClusters);      for (i = 0; i < m_NumClusters; i++) {	tempI[i] = new Instances(instances, 0);      }      for (i = 0; i < instances.numInstances(); i++) {	tempI[clusterAssignments[i]].add(instances.instance(i));      }      for (i = 0; i < m_NumClusters; i++) {	double [] vals = new double[instances.numAttributes()];	if (tempI[i].numInstances() == 0) {	  // empty cluster	  emptyClusterCount++;	} else {	  for (int j = 0; j < instances.numAttributes(); j++) {	    vals[j] = tempI[i].meanOrMode(j);	    m_ClusterNominalCounts[i][j] = 	      tempI[i].attributeStats(j).nominalCounts;	  }	  m_ClusterCentroids.add(new Instance(1.0, vals));	}      }      if (emptyClusterCount > 0) {	m_NumClusters -= emptyClusterCount;	tempI = new Instances[m_NumClusters];      }      if (!converged) {	m_squaredErrors = new double [m_NumClusters];	m_ClusterNominalCounts = new int [m_NumClusters][instances.numAttributes()][0];      }    }    m_ClusterStdDevs = new Instances(instances, m_NumClusters);    m_ClusterSizes = new int [m_NumClusters];    for (i = 0; i < m_NumClusters; i++) {      double [] vals2 = new double[instances.numAttributes()];      for (int j = 0; j < instances.numAttributes(); j++) {	if (instances.attribute(j).isNumeric()) {	  vals2[j] = Math.sqrt(tempI[i].variance(j));	} else {	  vals2[j] = Instance.missingValue();	}	      }      m_ClusterStdDevs.add(new Instance(1.0, vals2));      m_ClusterSizes[i] = tempI[i].numInstances();    }  }