}  if (data.checkForStringAttributes()) { throw new UnsupportedAttributeTypeException("Cannot handle string attributes!");
  public void buildClassifier(Instances data) throws Exception {    // Make sure K value is in range    if (m_KValue > data.numAttributes()-1) m_KValue = data.numAttributes()-1;    if (m_KValue < 1) m_KValue = (int) Utils.log2(data.numAttributes())+1;    // Check for non-nominal classes    if (!data.classAttribute().isNominal()) {      throw new UnsupportedClassTypeException("RandomTree: Nominal class, please.");    }    // Delete instances with missing class    data = new Instances(data);    data.deleteWithMissingClass();    if (data.numInstances() == 0) {      throw new IllegalArgumentException("RandomTree: zero training instances or all " +					 "instances have missing class!");    }    if (data.numAttributes() == 1) {      throw new IllegalArgumentException("RandomTree: Attribute missing. Need at least " +					 "one attribute other than class attribute!");    }    Instances train = data;    // Create array of sorted indices and weights    int[][] sortedIndices = new int[train.numAttributes()][0];    double[][] weights = new double[train.numAttributes()][0];    double[] vals = new double[train.numInstances()];    for (int j = 0; j < train.numAttributes(); j++) {      if (j != train.classIndex()) {	weights[j] = new double[train.numInstances()];	if (train.attribute(j).isNominal()) {	  // Handling nominal attributes. Putting indices of	  // instances with missing values at the end.	  sortedIndices[j] = new int[train.numInstances()];	  int count = 0;	  for (int i = 0; i < train.numInstances(); i++) {	    Instance inst = train.instance(i);	    if (!inst.isMissing(j)) {	      sortedIndices[j][count] = i;	      weights[j][count] = inst.weight();	      count++;	    }	  }	  for (int i = 0; i < train.numInstances(); i++) {	    Instance inst = train.instance(i);	    if (inst.isMissing(j)) {	      sortedIndices[j][count] = i;	      weights[j][count] = inst.weight();	      count++;	    }	  }	} else {	  	  // Sorted indices are computed for numeric attributes	  for (int i = 0; i < train.numInstances(); i++) {	    Instance inst = train.instance(i);	    vals[i] = inst.value(j);	  }	  sortedIndices[j] = Utils.sort(vals);	  for (int i = 0; i < train.numInstances(); i++) {	    weights[j][i] = train.instance(sortedIndices[j][i]).weight();	  }	}      }    }    // Compute initial class counts    double[] classProbs = new double[train.numClasses()];    for (int i = 0; i < train.numInstances(); i++) {      Instance inst = train.instance(i);      classProbs[(int)inst.classValue()] += inst.weight();    }    // Create the attribute indices window    int[] attIndicesWindow = new int[data.numAttributes()-1];    int j=0;    for (int i=0; i<attIndicesWindow.length; i++) {      if (j == data.classIndex()) j++; // do not include the class      attIndicesWindow[i] = j++;    }    // Build tree    buildTree(sortedIndices, weights, train, classProbs,	      new Instances(train, 0), m_MinNum, m_Debug,	      attIndicesWindow, data.getRandomNumberGenerator(m_randomSeed));  }