initCPTs(bayesNet);
    public void estimateCPTs(BayesNet bayesNet) throws Exception {        Instances instances = bayesNet.m_Instances;        // sanity check to see if nodes have not more than one parent        for (int iAttribute = 0; iAttribute < instances.numAttributes(); iAttribute++) {            if (bayesNet.getParentSet(iAttribute).getNrOfParents() > 1) {                throw new Exception("Cannot handle networks with nodes with more than 1 parent (yet).");            }        }        BayesNet EmptyNet = new BayesNet();        K2 oSearchAlgorithm = new K2();        oSearchAlgorithm.setInitAsNaiveBayes(false);        oSearchAlgorithm.setMaxNrOfParents(0);        EmptyNet.setSearchAlgorithm(oSearchAlgorithm);        EmptyNet.buildClassifier(instances);        BayesNet NBNet = new BayesNet();        oSearchAlgorithm.setInitAsNaiveBayes(true);        oSearchAlgorithm.setMaxNrOfParents(1);        NBNet.setSearchAlgorithm(oSearchAlgorithm);        NBNet.buildClassifier(instances);        // estimate CPTs        for (int iAttribute = 0; iAttribute < instances.numAttributes(); iAttribute++) {            if (iAttribute != instances.classIndex()) {                  double w1 = 0.0, w2 = 0.0;                  int nAttValues = instances.attribute(iAttribute).numValues();                  if (m_bUseK2Prior == true) {                      // use Cooper and Herskovitz's metric                      for (int iAttValue = 0; iAttValue < nAttValues; iAttValue++) {                        w1 += Statistics.lnGamma(1 + ((DiscreteEstimatorBayes)EmptyNet.m_Distributions[iAttribute][0]).getCount(iAttValue))                              - Statistics.lnGamma(1);                      }                      w1 += Statistics.lnGamma(nAttValues) - Statistics.lnGamma(nAttValues + instances.numInstances());                      for (int iParent = 0; iParent < bayesNet.getParentSet(iAttribute).getCardinalityOfParents(); iParent++) {                        int nTotal = 0;                          for (int iAttValue = 0; iAttValue < nAttValues; iAttValue++) {                            double nCount = ((DiscreteEstimatorBayes)NBNet.m_Distributions[iAttribute][iParent]).getCount(iAttValue);                            w2 += Statistics.lnGamma(1 + nCount)                                  - Statistics.lnGamma(1);                            nTotal += nCount;                          }                        w2 += Statistics.lnGamma(nAttValues) - Statistics.lnGamma(nAttValues + nTotal);                      }                  } else {                      // use BDe metric                      for (int iAttValue = 0; iAttValue < nAttValues; iAttValue++) {                        w1 += Statistics.lnGamma(1.0/nAttValues + ((DiscreteEstimatorBayes)EmptyNet.m_Distributions[iAttribute][0]).getCount(iAttValue))                              - Statistics.lnGamma(1.0/nAttValues);                      }                      w1 += Statistics.lnGamma(1) - Statistics.lnGamma(1 + instances.numInstances());                      int nParentValues = bayesNet.getParentSet(iAttribute).getCardinalityOfParents();                      for (int iParent = 0; iParent < nParentValues; iParent++) {                        int nTotal = 0;                          for (int iAttValue = 0; iAttValue < nAttValues; iAttValue++) {                            double nCount = ((DiscreteEstimatorBayes)NBNet.m_Distributions[iAttribute][iParent]).getCount(iAttValue);                            w2 += Statistics.lnGamma(1.0/(nAttValues * nParentValues) + nCount)                                  - Statistics.lnGamma(1.0/(nAttValues * nParentValues));                            nTotal += nCount;                          }                        w2 += Statistics.lnGamma(1) - Statistics.lnGamma(1 + nTotal);                      }                  }		//    System.out.println(w1 + " " + w2 + " " + (w2 - w1));                  if (w1 < w2) {                    w2 = w2 - w1;                    w1 = 0;                    w1 = 1 / (1 + Math.exp(w2));                    w2 = Math.exp(w2) / (1 + Math.exp(w2));                  } else {                    w1 = w1 - w2;                    w2 = 0;                    w2 = 1 / (1 + Math.exp(w1));                    w1 = Math.exp(w1) / (1 + Math.exp(w1));                  }		                  for (int iParent = 0; iParent < bayesNet.getParentSet(iAttribute).getCardinalityOfParents(); iParent++) {                      bayesNet.m_Distributions[iAttribute][iParent] =                       new DiscreteEstimatorFullBayes(                        instances.attribute(iAttribute).numValues(),                         w1, w2,                        (DiscreteEstimatorBayes) EmptyNet.m_Distributions[iAttribute][0],                        (DiscreteEstimatorBayes) NBNet.m_Distributions[iAttribute][iParent],                        m_fAlpha                       );                  }             }        }        int iAttribute = instances.classIndex();        bayesNet.m_Distributions[iAttribute][0] = EmptyNet.m_Distributions[iAttribute][0];    } // estimateCPTs