inst.classValue() * inst.classValue() * weights[0][i]; totalSumOfWeights += weights[0][i];
inst.classValue() * inst.classValue() * weights[helpIndex][i]; totalSumOfWeights += weights[helpIndex][i];
    protected void buildTree(int[][] sortedIndices, double[][] weights,			     Instances data, double totalWeight, 			     double[] classProbs, Instances header,			     double minNum, double minVariance,			     int depth, int maxDepth)       throws Exception {            // Store structure of dataset, set minimum number of instances      // and make space for potential info from pruning data      m_Info = header;      m_HoldOutDist = new double[data.numClasses()];	      // Make leaf if there are no training instances      if (sortedIndices[0].length == 0) {	if (data.classAttribute().isNumeric()) {	  m_Distribution = new double[2];	} else {	  m_Distribution = new double[data.numClasses()];	}	m_ClassProbs = null;	return;      }            double priorVar = 0;      if (data.classAttribute().isNumeric()) {	// Compute prior variance	double totalSum = 0, totalSumSquared = 0, totalSumOfWeights = 0; 	for (int i = 0; i < sortedIndices[0].length; i++) {	  Instance inst = data.instance(sortedIndices[0][i]);	  totalSum += inst.classValue() * weights[0][i];	  totalSumSquared += 	    inst.classValue() * inst.classValue() * weights[0][i];	  totalSumOfWeights += weights[0][i];	}	priorVar = singleVariance(totalSum, totalSumSquared, 				  totalSumOfWeights);      }      // Check if node doesn't contain enough instances, is pure      // or the maximum tree depth is reached      m_ClassProbs = new double[classProbs.length];      System.arraycopy(classProbs, 0, m_ClassProbs, 0, classProbs.length);      if ((totalWeight < (2 * minNum)) ||	  // Nominal case	  (data.classAttribute().isNominal() &&	   Utils.eq(m_ClassProbs[Utils.maxIndex(m_ClassProbs)],		    Utils.sum(m_ClassProbs))) ||	  // Numeric case	  (data.classAttribute().isNumeric() && 	   ((priorVar / totalWeight) < minVariance)) ||	  // Check tree depth	  ((m_MaxDepth >= 0) && (depth >= maxDepth))) {	// Make leaf	m_Attribute = -1;	if (data.classAttribute().isNominal()) {	  // Nominal case	  m_Distribution = new double[m_ClassProbs.length];	  for (int i = 0; i < m_ClassProbs.length; i++) {	    m_Distribution[i] = m_ClassProbs[i];	  }	  Utils.normalize(m_ClassProbs);	} else {	  // Numeric case	  m_Distribution = new double[2];	  m_Distribution[0] = priorVar;	  m_Distribution[1] = totalWeight;	}	return;      }      // Compute class distributions and value of splitting      // criterion for each attribute      double[] vals = new double[data.numAttributes()];      double[][][] dists = new double[data.numAttributes()][0][0];      double[][] props = new double[data.numAttributes()][0];      double[][] totalSubsetWeights = new double[data.numAttributes()][0];      double[] splits = new double[data.numAttributes()];      if (data.classAttribute().isNominal()) { 	// Nominal case	for (int i = 0; i < data.numAttributes(); i++) {	  if (i != data.classIndex()) {	    splits[i] = distribution(props, dists, i, sortedIndices[i], 				     weights[i], totalSubsetWeights, data);	    vals[i] = gain(dists[i], priorVal(dists[i]));	  }	}      } else {	// Numeric case	for (int i = 0; i < data.numAttributes(); i++) {	  if (i != data.classIndex()) {	    splits[i] = 	      numericDistribution(props, dists, i, sortedIndices[i], 				  weights[i], totalSubsetWeights, data, 				  vals);	  }	}      }      // Find best attribute      m_Attribute = Utils.maxIndex(vals);      int numAttVals = dists[m_Attribute].length;      // Check if there are at least two subsets with      // required minimum number of instances      int count = 0;      for (int i = 0; i < numAttVals; i++) {	if (totalSubsetWeights[m_Attribute][i] >= minNum) {	  count++;	}	if (count > 1) {	  break;	}      }      // Any useful split found?      if ((vals[m_Attribute] > 0) && (count > 1)) {	// Build subtrees	m_SplitPoint = splits[m_Attribute];	m_Prop = props[m_Attribute];	int[][][] subsetIndices = 	  new int[numAttVals][data.numAttributes()][0];	double[][][] subsetWeights = 	  new double[numAttVals][data.numAttributes()][0];	splitData(subsetIndices, subsetWeights, m_Attribute, m_SplitPoint, 		  sortedIndices, weights, data);	m_Successors = new Tree[numAttVals];	for (int i = 0; i < numAttVals; i++) {	  m_Successors[i] = new Tree();	  m_Successors[i].	    buildTree(subsetIndices[i], subsetWeights[i], 		      data, totalSubsetWeights[m_Attribute][i],		      dists[m_Attribute][i], header, minNum, 		      minVariance, depth + 1, maxDepth);	}      } else {      	// Make leaf	m_Attribute = -1;      }      // Normalize class counts      if (data.classAttribute().isNominal()) {	m_Distribution = new double[m_ClassProbs.length];	for (int i = 0; i < m_ClassProbs.length; i++) {	    m_Distribution[i] = m_ClassProbs[i];	}	Utils.normalize(m_ClassProbs);      } else {	m_Distribution = new double[2];	m_Distribution[0] = priorVar;	m_Distribution[1] = totalWeight;      }    }