private double calcNodeScorePlain(int nNode) {
    Instances instances = m_BayesNet.m_Instances;
    ParentSet oParentSet = m_BayesNet.getParentSet(nNode);

    // determine cardinality of parent set & reserve space for frequency counts
    int nCardinality = oParentSet.getCardinalityOfParents();
    int numValues = instances.attribute(nNode).numValues();
    int[] nCounts = new int[nCardinality * numValues];

    // initialize (don't need this?)
    for (int iParent = 0; iParent < nCardinality * numValues; iParent++) {
      nCounts[iParent] = 0;
    }

    // estimate distributions
    Enumeration enumInsts = instances.enumerateInstances();

    while (enumInsts.hasMoreElements()) {
      Instance instance = (Instance) enumInsts.nextElement();

      // updateClassifier;
      double iCPT = 0;

      for (int iParent = 0; iParent < oParentSet.getNrOfParents(); iParent++) {
        int nParent = oParentSet.getParent(iParent);

        iCPT = iCPT * instances.attribute(nParent).numValues() + instance.value(nParent);
      }

      nCounts[numValues * ((int) iCPT) + (int) instance.value(nNode)]++;
    }

    return calcScoreOfCounts(nCounts, nCardinality, numValues, instances);
  } // CalcNodeScore
  /**
   * helper function for CalcNodeScore above using the ADTree data structure
   *
   * @param nNode node for which the score is calculate
   * @return log score
   */
  private double calcNodeScoreADTree(int nNode) {
    Instances instances = m_BayesNet.m_Instances;
    ParentSet oParentSet = m_BayesNet.getParentSet(nNode);
    // get set of parents, insert iNode
    int nNrOfParents = oParentSet.getNrOfParents();
    int[] nNodes = new int[nNrOfParents + 1];
    for (int iParent = 0; iParent < nNrOfParents; iParent++) {
      nNodes[iParent] = oParentSet.getParent(iParent);
    }
    nNodes[nNrOfParents] = nNode;

    // calculate offsets
    int[] nOffsets = new int[nNrOfParents + 1];
    int nOffset = 1;
    nOffsets[nNrOfParents] = 1;
    nOffset *= instances.attribute(nNode).numValues();
    for (int iNode = nNrOfParents - 1; iNode >= 0; iNode--) {
      nOffsets[iNode] = nOffset;
      nOffset *= instances.attribute(nNodes[iNode]).numValues();
    }

    // sort nNodes & offsets
    for (int iNode = 1; iNode < nNodes.length; iNode++) {
      int iNode2 = iNode;
      while (iNode2 > 0 && nNodes[iNode2] < nNodes[iNode2 - 1]) {
        int h = nNodes[iNode2];
        nNodes[iNode2] = nNodes[iNode2 - 1];
        nNodes[iNode2 - 1] = h;
        h = nOffsets[iNode2];
        nOffsets[iNode2] = nOffsets[iNode2 - 1];
        nOffsets[iNode2 - 1] = h;
        iNode2--;
      }
    }

    // get counts from ADTree
    int nCardinality = oParentSet.getCardinalityOfParents();
    int numValues = instances.attribute(nNode).numValues();
    int[] nCounts = new int[nCardinality * numValues];
    // if (nNrOfParents > 1) {

    m_BayesNet.getADTree().getCounts(nCounts, nNodes, nOffsets, 0, 0, false);

    return calcScoreOfCounts(nCounts, nCardinality, numValues, instances);
  } // CalcNodeScore