m_CondiCounts = new double[m_NumClasses][m_TotalAttValues][m_TotalAttValues];
m_ClassAttAttCounts = new double[m_NumClasses][m_TotalAttValues][m_TotalAttValues];
  public void buildClassifier(Instances instances) throws Exception {    // judge dataset    // class    if (instances.classIndex() == -1)      throw new UnassignedClassException("No class attribute set!");    if (!instances.classAttribute().isNominal())      throw new UnsupportedClassTypeException("Handles only nominal classes!");        // attributes    Enumeration enumInsts,enumAtts;    enumAtts = instances.enumerateAttributes();    while (enumAtts.hasMoreElements()) {      Attribute attribute = (Attribute) enumAtts.nextElement();      if (attribute.type()!= Attribute.NOMINAL){        throw new UnsupportedAttributeTypeException("Handles nominal variables only.");      }      enumInsts = instances.enumerateInstances();      while (enumInsts.hasMoreElements()) {        if (((Instance) enumInsts.nextElement()).isMissing(attribute)) {          throw new NoSupportForMissingValuesException("Can't handle missing values.");        }      }    }    // reset variable    m_NumClasses = instances.numClasses();    m_ClassIndex = instances.classIndex();    m_NumAttributes = instances.numAttributes();    m_NumInstances = instances.numInstances();    m_TotalAttValues = 0;    // allocate space for attribute reference arrays    m_StartAttIndex = new int[m_NumAttributes];    m_NumAttValues = new int[m_NumAttributes];    // set the starting index of each attribute and the number of values for    // each attribute and the total number of values for all attributes (not    // including class).    for(int i = 0; i < m_NumAttributes; i++) {      if(i != m_ClassIndex) {        m_StartAttIndex[i] = m_TotalAttValues;        m_NumAttValues[i] = instances.attribute(i).numValues();        m_TotalAttValues += m_NumAttValues[i];      }      else {        m_StartAttIndex[i] = -1;        m_NumAttValues[i] = m_NumClasses;      }    }    // allocate space for counts and frequencies    m_ClassCounts = new double[m_NumClasses];    m_CondiCounts = new double[m_NumClasses][m_TotalAttValues][m_TotalAttValues];    // Calculate the counts    for(int k = 0; k < m_NumInstances; k++) {      int classVal=(int)instances.instance(k).classValue();      m_ClassCounts[classVal] ++;      int[] attIndex = new int[m_NumAttributes];      for(int i = 0; i < m_NumAttributes; i++) {        if(i == m_ClassIndex)          attIndex[i] = -1;        else          attIndex[i] = m_StartAttIndex[i] + (int)instances.instance(k).value(i);      }      for(int Att1 = 0; Att1 < m_NumAttributes; Att1++) {        if(attIndex[Att1] == -1) continue;        for(int Att2 = 0; Att2 < m_NumAttributes; Att2++) {          if((attIndex[Att2] != -1)) {            m_CondiCounts[classVal][attIndex[Att1]][attIndex[Att2]] ++;          }        }      }    }    //compute conditional mutual information of each pair attributes    m_conditionalMutualInformation=new double[m_NumAttributes-1][m_NumAttributes-1];    for(int son=0;son<m_NumAttributes-1;son++){      for(int parent=0;parent<m_NumAttributes-1;parent++){        if(son==parent)continue;        m_conditionalMutualInformation[son][parent]=conditionalMutualInfo(son,parent);      }    }  }