Program: 32008
Project: 32008
Buggy source:
@Override public GainInfo computeImpurity(double[] stats,ColumnConfig config){
  int numClasses=super.statsSize;
  double[] statsByClasses=new double[numClasses];
  for (int i=0; i < stats.length / numClasses; i++) {
    for (int j=0; j < numClasses; j++) {
      double oneStatValue=stats[i * super.statsSize + j];
      statsByClasses[j]+=oneStatValue;
    }
  }
  List<Pair> categoricalOrderList=null;
  if (config.isCategorical()) {
    categoricalOrderList=getCategoricalOrderList(stats,stats.length / super.statsSize);
  }
  InternalEntropyInfo info=getGiniInfo(statsByClasses);
  Predict predict=new Predict(info.sumAll == 0d ? 0d : statsByClasses[1] / info.sumAll,info.indexOfLargestElement);
  double[] leftStatByClasses=new double[numClasses];
  double[] rightStatByClasses=new double[numClasses];
  List<GainInfo> internalGainList=new ArrayList<GainInfo>();
  Set<String> leftCategories=config.isCategorical() ? new HashSet<String>() : null;
  for (int i=0; i < (stats.length / numClasses - 1); i++) {
    int index=i;
    if (config.isCategorical()) {
      index=categoricalOrderList.get(i).index;
    }
    for (int j=0; j < leftStatByClasses.length; j++) {
      leftStatByClasses[j]+=stats[index * numClasses + j];
    }
    InternalEntropyInfo leftInfo=getGiniInfo(leftStatByClasses);
    Predict leftPredict=new Predict(leftInfo.sumAll == 0d ? 0d : leftStatByClasses[1] / leftInfo.sumAll,leftInfo.indexOfLargestElement);
    for (int j=0; j < leftStatByClasses.length; j++) {
      rightStatByClasses[j]=statsByClasses[j] - leftStatByClasses[j];
    }
    InternalEntropyInfo rightInfo=getGiniInfo(rightStatByClasses);
    if (leftInfo.sumAll <= minInstancesPerNode || rightInfo.sumAll <= minInstancesPerNode) {
      continue;
    }
    Predict rightPredict=new Predict(rightInfo.sumAll == 0d ? 0d : rightStatByClasses[1] / rightInfo.sumAll,rightInfo.indexOfLargestElement);
    double leftWeight=info.sumAll == 0d ? 0d : (leftInfo.sumAll / info.sumAll);
    double rightWeight=info.sumAll == 0d ? 0d : (rightInfo.sumAll / info.sumAll);
    double gain=info.impurity - leftWeight * leftInfo.impurity - rightWeight * rightInfo.impurity;
    if (gain <= minInfoGain) {
      continue;
    }
    Split split=null;
    if (config.isCategorical()) {
      leftCategories.add(config.getBinCategory().get(i));
      split=new Split(config.getColumnNum(),FeatureType.CATEGORICAL,0d,leftCategories);
    }
 else {
      split=new Split(config.getColumnNum(),FeatureType.CONTINUOUS,config.getBinBoundary().get(i + 1),null);
    }
    internalGainList.add(new GainInfo(gain,info.impurity,predict,leftInfo.impurity,rightInfo.impurity,leftPredict,rightPredict,split));
  }
  return GainInfo.getGainInfoByMaxGain(internalGainList);
}

Fixed version (ground truth):
@Override public GainInfo computeImpurity(double[] stats,ColumnConfig config){
  int numClasses=super.statsSize;
  double[] statsByClasses=new double[numClasses];
  for (int i=0; i < stats.length / numClasses; i++) {
    for (int j=0; j < numClasses; j++) {
      double oneStatValue=stats[i * super.statsSize + j];
      statsByClasses[j]+=oneStatValue;
    }
  }
  List<Pair> categoricalOrderList=null;
  if (config.isCategorical()) {
    categoricalOrderList=getCategoricalOrderList(stats,stats.length / super.statsSize);
  }
  InternalGiniInfo info=getGiniInfo(statsByClasses);
  Predict predict=new Predict(info.sumAll == 0d ? 0d : statsByClasses[1] / info.sumAll,info.indexOfLargestElement);
  double[] leftStatByClasses=new double[numClasses];
  double[] rightStatByClasses=new double[numClasses];
  List<GainInfo> internalGainList=new ArrayList<GainInfo>();
  Set<String> leftCategories=config.isCategorical() ? new HashSet<String>() : null;
  for (int i=0; i < (stats.length / numClasses - 1); i++) {
    int index=i;
    if (config.isCategorical()) {
      index=categoricalOrderList.get(i).index;
    }
    for (int j=0; j < leftStatByClasses.length; j++) {
      leftStatByClasses[j]+=stats[index * numClasses + j];
    }
    InternalGiniInfo leftInfo=getGiniInfo(leftStatByClasses);
    Predict leftPredict=new Predict(leftInfo.sumAll == 0d ? 0d : leftStatByClasses[1] / leftInfo.sumAll,leftInfo.indexOfLargestElement);
    for (int j=0; j < leftStatByClasses.length; j++) {
      rightStatByClasses[j]=statsByClasses[j] - leftStatByClasses[j];
    }
    InternalGiniInfo rightInfo=getGiniInfo(rightStatByClasses);
    if (leftInfo.sumAll <= minInstancesPerNode || rightInfo.sumAll <= minInstancesPerNode) {
      continue;
    }
    Predict rightPredict=new Predict(rightInfo.sumAll == 0d ? 0d : rightStatByClasses[1] / rightInfo.sumAll,rightInfo.indexOfLargestElement);
    double leftWeight=info.sumAll == 0d ? 0d : (leftInfo.sumAll / info.sumAll);
    double rightWeight=info.sumAll == 0d ? 0d : (rightInfo.sumAll / info.sumAll);
    double gain=info.impurity - leftWeight * leftInfo.impurity - rightWeight * rightInfo.impurity;
    if (gain <= minInfoGain) {
      continue;
    }
    Split split=null;
    if (config.isCategorical()) {
      if (index >= config.getBinCategory().size()) {
        leftCategories.add("String_Node_Str");
      }
 else {
        leftCategories.add(config.getBinCategory().get(index));
      }
      split=new Split(config.getColumnNum(),FeatureType.CATEGORICAL,0d,new HashSet<String>(leftCategories));
    }
 else {
      split=new Split(config.getColumnNum(),FeatureType.CONTINUOUS,config.getBinBoundary().get(index + 1),null);
    }
    internalGainList.add(new GainInfo(gain,info.impurity,predict,leftInfo.impurity,rightInfo.impurity,leftPredict,rightPredict,split));
  }
  return GainInfo.getGainInfoByMaxGain(internalGainList);
}