@Deprecated private static DiscordRecord findBestDiscordWithHash(double[] series,int windowSize,HashMap<String,ArrayList<Integer>> hash,VisitRegistry globalRegistry,double nThreshold) throws Exception {
  ArrayList<FrequencyTableEntry> frequencies=hashToFreqEntries(hash);
  Collections.sort(frequencies);
  int bestSoFarPosition=-1;
  double bestSoFarDistance=0.0D;
  String bestSoFarWord="";
  int iterationCounter=0;
  int distanceCalls=0;
  while (!frequencies.isEmpty()) {
    iterationCounter++;
    FrequencyTableEntry currentEntry=frequencies.remove(0);
    String currentWord=String.valueOf(currentEntry.getStr());
    int currentPos=currentEntry.getPosition();
    if (globalRegistry.isVisited(currentPos)) {
      continue;
    }
    VisitRegistry randomRegistry=new VisitRegistry(series.length);
    randomRegistry.markVisited(series.length - windowSize,series.length);
    int markStart=currentPos - windowSize;
    if (markStart < 0) {
      markStart=0;
    }
    int markEnd=currentPos + windowSize;
    if (markEnd > series.length) {
      markEnd=series.length;
    }
    randomRegistry.markVisited(markStart,markEnd);
    LOGGER.trace("conducting search for {} at {}, iteration {}, to go: {}",currentWord,currentPos,iterationCounter,frequencies.size());
    double[] currentCandidateSeq=tp.znorm(tp.subseriesByCopy(series,currentPos,currentPos + windowSize),nThreshold);
    double nearestNeighborDist=Double.MAX_VALUE;
    boolean doRandomSearch=true;
    List<Integer> currentWordOccurrences=hash.get(currentWord);
    for (    Integer nextOccurrence : currentWordOccurrences) {
      if (randomRegistry.isVisited(nextOccurrence.intValue())) {
        continue;
      }
 else {
        randomRegistry.markVisited(nextOccurrence.intValue());
      }
      double[] occurrenceSubsequence=tp.znorm(tp.subseriesByCopy(series,nextOccurrence,nextOccurrence + windowSize),nThreshold);
      double dist=ed.distance(currentCandidateSeq,occurrenceSubsequence);
      distanceCalls++;
      if (dist < nearestNeighborDist) {
        nearestNeighborDist=dist;
        LOGGER.trace(" ** current NN at {}, distance: {}, pos {}" + nextOccurrence,nearestNeighborDist,currentPos);
      }
      if (dist < bestSoFarDistance) {
        LOGGER.trace(" ** abandoning random visits loop, seen distance {} at iteration {}",dist,bestSoFarDistance);
        doRandomSearch=false;
        break;
      }
    }
    if (doRandomSearch) {
      LOGGER.trace("starting random search");
      int visitCounter=0;
      int randomPos=-1;
      while (-1 != (randomPos=randomRegistry.getNextRandomUnvisitedPosition())) {
        randomRegistry.markVisited(randomPos);
        double[] randomSubsequence=tp.znorm(tp.subseriesByCopy(series,randomPos,randomPos + windowSize),nThreshold);
        double dist=ed.distance(currentCandidateSeq,randomSubsequence);
        distanceCalls++;
        if (dist < bestSoFarDistance) {
          nearestNeighborDist=dist;
          LOGGER.trace(" ** abandoning random visits loop, seen distance {} at iteration {}",nearestNeighborDist,visitCounter);
          break;
        }
        if (dist < nearestNeighborDist) {
          LOGGER.trace(" ** current NN at {}, distance: {}, pos {}" + randomPos,dist,currentPos);
          nearestNeighborDist=dist;
        }
        visitCounter=visitCounter + 1;
      }
    }
    if (nearestNeighborDist > bestSoFarDistance) {
      LOGGER.debug("discord updated: pos {}, dist {}",currentPos,bestSoFarDistance);
      bestSoFarDistance=nearestNeighborDist;
      bestSoFarPosition=currentPos;
      bestSoFarWord=currentWord;
    }
    LOGGER.trace(" . . iterated {} times, best distance: {} for a string {} at {}",iterationCounter,bestSoFarDistance,bestSoFarWord,bestSoFarPosition);
  }
  LOGGER.trace("Distance calls: {}",distanceCalls);
  DiscordRecord res=new DiscordRecord(bestSoFarPosition,bestSoFarDistance,bestSoFarWord);
  res.setLength(windowSize);
  res.setInfo("distance calls: " + distanceCalls);
  return res;
}

@ Deprecated private static DiscordRecord findBestDiscordWithHash ( double [ ] series , int windowSize , HashMap < String , ArrayList < Integer > > hash , VisitRegistry globalRegistry , double nThreshold ) throws Exception { ArrayList < FrequencyTableEntry > frequencies = hashToFreqEntries ( hash ) ; Collections . sort ( frequencies ) ; int bestSoFarPosition = - 1 ; double bestSoFarDistance = 0.0D ; String bestSoFarWord = "" ; int iterationCounter = 0 ; int distanceCalls = 0 ; while ( ! frequencies . isEmpty ( ) ) { iterationCounter ++ ; FrequencyTableEntry currentEntry = frequencies . remove ( 0 ) ; String currentWord = String . valueOf ( currentEntry . getStr ( ) ) ; int currentPos = currentEntry . getPosition ( ) ; if ( globalRegistry . isVisited ( currentPos ) ) { continue ; } VisitRegistry randomRegistry = new VisitRegistry ( series . length ) ; randomRegistry . markVisited ( series . length - windowSize , series . length ) ; int markStart = currentPos - windowSize ; if ( markStart < 0 ) { markStart = 0 ; } int markEnd = currentPos + windowSize ; if ( markEnd > series . length ) { markEnd = series . length ; } randomRegistry . markVisited ( markStart , markEnd ) ; LOGGER . trace ( "conducting search for {} at {}, iteration {}, to go: {}" , currentWord , currentPos , iterationCounter , frequencies . size ( ) ) ; double [ ] currentCandidateSeq = tp . znorm ( tp . subseriesByCopy ( series , currentPos , currentPos + windowSize ) , nThreshold ) ; double nearestNeighborDist = Double . MAX_VALUE ; boolean doRandomSearch = true ; List < Integer > currentWordOccurrences = hash . get ( currentWord ) ; for ( Integer nextOccurrence : currentWordOccurrences ) { if ( randomRegistry . isVisited ( nextOccurrence . intValue ( ) ) ) { continue ; } else { randomRegistry . markVisited ( nextOccurrence . intValue ( ) ) ; } double [ ] occurrenceSubsequence = tp . znorm ( tp . subseriesByCopy ( series , nextOccurrence , nextOccurrence + windowSize ) , nThreshold ) ; double dist = ed . distance ( currentCandidateSeq , occurrenceSubsequence ) ; distanceCalls ++ ; if ( dist < nearestNeighborDist ) { nearestNeighborDist = dist ; LOGGER . trace ( " ** current NN at {}, distance: {}, pos {}" + nextOccurrence , nearestNeighborDist , currentPos ) ; } if ( dist < bestSoFarDistance ) { LOGGER . trace ( " ** abandoning random visits loop, seen distance {} at iteration {}" , dist , bestSoFarDistance ) ; doRandomSearch = false ; break ; } } if ( doRandomSearch ) { LOGGER . trace ( "starting random search" ) ; int visitCounter = 0 ; int randomPos = - 1 ; while ( - 1 != ( randomPos = randomRegistry . getNextRandomUnvisitedPosition ( ) ) ) { randomRegistry . markVisited ( randomPos ) ; double [ ] randomSubsequence = tp . znorm ( tp . subseriesByCopy ( series , randomPos , randomPos + windowSize ) , nThreshold ) ; double dist = ed . distance ( currentCandidateSeq , randomSubsequence ) ; distanceCalls ++ ; if ( dist < bestSoFarDistance ) { nearestNeighborDist = dist ; LOGGER . trace ( " ** abandoning random visits loop, seen distance {} at iteration {}" , nearestNeighborDist , visitCounter ) ; break ; } if ( dist < nearestNeighborDist ) { LOGGER . trace ( " ** current NN at {}, distance: {}, pos {}" + randomPos , dist , currentPos ) ; nearestNeighborDist = dist ; } visitCounter = visitCounter + 1 ; } } if ( nearestNeighborDist > bestSoFarDistance ) { LOGGER . debug ( "discord updated: pos {}, dist {}" , currentPos , bestSoFarDistance ) ; bestSoFarDistance = nearestNeighborDist ; bestSoFarPosition = currentPos ; bestSoFarWord = currentWord ; } LOGGER . trace ( " . . iterated {} times, best distance: {} for a string {} at {}" , iterationCounter , bestSoFarDistance , bestSoFarWord , bestSoFarPosition ) ; } LOGGER . trace ( "Distance calls: {}" , distanceCalls ) ; DiscordRecord res = new DiscordRecord ( bestSoFarPosition , bestSoFarDistance , bestSoFarWord ) ; res . setLength ( windowSize ) ; res . setInfo ( "distance calls: " + distanceCalls ) ; return res ; }
this method reports the best found discord . note , that this discord is approximately the best . due to the fuzzy - logic search with randomization and aggressive labeling of the magic array locations .
