protected void initParser(final ParseTask parseTask) {
    chart = new CellChart(parseTask, this);
    this.maxEdgeFOM = new float[chart.size()][chart.size() + 1];
    this.spanAgenda = new PriorityQueue<HashSetChartCell>();

    // The chart is (chart.size()+1)*chart.size()/2
    for (int start = 0; start < chart.size(); start++) {
      for (int end = start + 1; end < chart.size() + 1; end++) {
        maxEdgeFOM[start][end] = Float.NEGATIVE_INFINITY;
      }
    }
  }
 protected HashSetChartCell next() {
   // return spanAgenda.poll();
   HashSetChartCell bestSpan = null;
   float bestScore = Float.NEGATIVE_INFINITY;
   for (int span = 1; span <= chart.size(); span++) {
     for (int beg = 0; beg < chart.size() - span + 1; beg++) { // beginning
       if (maxEdgeFOM[beg][beg + span] > bestScore) {
         bestScore = maxEdgeFOM[beg][beg + span];
         bestSpan = chart.getCell(beg, beg + span);
       }
     }
   }
   return bestSpan;
 }
 public void addUnaryExtensionsToLexProds() {
   for (int i = 0; i < chart.size(); i++) {
     final HashSetChartCell cell = chart.getCell(i, i + 1);
     for (final int pos : cell.getPosNTs()) {
       for (final Production unaryProd : grammar.getUnaryProductionsWithChild(pos)) {
         // cell.addEdge(unaryProd, cell, null, cell.getBestEdge(pos).inside + unaryProd.prob);
         cell.updateInside(unaryProd, cell.getInside(pos) + unaryProd.prob);
       }
     }
   }
 }
  protected void expandFrontier(final HashSetChartCell cell) {

    // connect edge as possible right non-term
    for (int start = 0; start < cell.start(); start++) {
      setSpanMaxEdgeFOM(chart.getCell(start, cell.start()), cell);
    }

    // connect edge as possible left non-term
    for (int end = cell.end() + 1; end <= chart.size(); end++) {
      setSpanMaxEdgeFOM(cell, chart.getCell(cell.end(), end));
    }
  }
 protected void addLexicalProductions(final int sent[]) {
   // ChartEdge newEdge;
   HashSetChartCell cell;
   for (int i = 0; i < chart.size(); i++) {
     cell = chart.getCell(i, i + 1);
     for (final Production lexProd : grammar.getLexicalProductionsWithChild(sent[i])) {
       // newEdge = chart.new ChartEdge(lexProd, chart.getCell(i, i + 1));
       // chart.getCell(i, i + 1).addEdge(newEdge);
       cell.updateInside(lexProd, lexProd.prob);
     }
   }
 }
  @Override
  public BinaryTree<String> findBestParse(final ParseTask parseTask) {
    HashSetChartCell cell;

    initParser(parseTask);
    addLexicalProductions(parseTask.tokens);
    figureOfMerit.initSentence(parseTask, chart);
    addUnaryExtensionsToLexProds();

    for (int i = 0; i < chart.size(); i++) {
      expandFrontier(chart.getCell(i, i + 1));
    }

    while (hasNext() && !chart.hasCompleteParse(grammar.startSymbol)) {
      cell = next();
      // System.out.println(" nextCell: " + cell);
      visitCell(cell);
      expandFrontier(cell);
    }

    return chart.extractBestParse(grammar.startSymbol);
  }