if (Debug.level >= 20) { System.err.println(structure.getClass().getName() + "\n\t" + event); }  if (useCache) { Double cacheProb = topLevelCache.getProb(event); if (cacheProb != null) return cacheProb.doubleValue(); }  int highestCachedLevel = numLevels;
  protected double estimateProb(ProbabilityStructure structure,				TrainerEvent event) {    // check cache here!    structure.prevHistCount = 0;    for (int level = 0; level < numLevels; level++) {      if (level == specialLevel)	estimateSpecialLevelProb(structure, event);      // check cache here!!!!!!!!!!!!            Event history = structure.getHistory(event, level);      Transition transition = structure.getTransition(event, level);      CountsTrio trio = counts[level];      double historyCount = trio.history().count(history);      double transitionCount = trio.transition().count(transition);      double uniqueCount = trio.unique().count(history);      double lambda, estimate, adjustment = 1.0;      double fudge = structure.lambdaFudge(level);      if (historyCount == 0) {	lambda = 0;	estimate = 0;      }      else {	if (structure.prevHistCount <= historyCount)	  adjustment = 1 - structure.prevHistCount / historyCount;	lambda =	  adjustment * (historyCount / (historyCount + fudge * uniqueCount));	estimate = transitionCount / historyCount;      }      // cache probVal here!!!!!!!!!!!!      structure.lambdas[level] = lambda;      structure.estimates[level] = estimate;      structure.prevHistCount = historyCount;    }    double prob = 0.0;    for (int level = numLevels - 1; level >= 0; level--) {      double lambda = structure.lambdas[level];      double estimate = structure.estimates[level];      prob = lambda * estimate + ((1 - lambda) * prob);    }    // cache prob here!!!!!!!!!!!!!    return prob;  }