/* itgdec-lzkbest.cpp
 * the lazy kbest decoder as described in Liang and Chiang (2007)
 * $Id: itgdec-lzkbest.cpp,v 1.2 2011/10/16 22:36:43 gildea Exp $
 */

#include "itgdec-lzkbest.h"

#define TRUECOST

//#define MAXKBUFSIZE 10000

double CYKDecoder::rootlmcost(int *u, int *v){
  double lm_prob = 0.0;

  if (ngram->N == 2) {
    lm_prob = LMWEIGHT * (ngram->bigram(-1, u[0]) + ngram->bigram(v[0], -2));
  } else { // trigram
    lm_prob = LMWEIGHT * (ngram->trigram(-1, u[0], u[1]) 
			  + ngram->trigram(v[1], v[0], -2));
    lm_prob += LMWEIGHT * (ngram->bigram(-1, u[0])); //adding the leading bigram probability
  }

  return lm_prob;

}

void CYKDecoder::lazyjthbest(int s, int t, int n, unsigned int j){
  int rhs, S;
  //  DINT ul[2], vl[2], ur[2], vr[2], u[2], v[2];
  double sita0, sita3, sita30, Pr, oldsita, newsita;
  ITGDCell *pd=NULL; //pointer to a decoding chart cel
  ITGDCell *pdd=NULL; //pointer to a decoding chart cell
  int uchoice[2];
  int vchoice[2];
  int nl, nr;

  kb_item_t theinode;

  //  printf("%d, %d, %d, %d\n", s, t, n, j);

  //initialization , if not explored yet

  if (KBESTS(s, t, n)->KV.size()==0){//not explored yet
    if ((s==0)&&(t==T)&&(n==grammar->_nonterminal_cnt)){//the root node 
      lazyjthbest(s, t, grammar->start_symbol, 1);
      if (KBESTS(s, t, grammar->start_symbol)->KV.size()>0){//make sure we do have the first best in the buffer 
	theinode.l=1;
	DUEXASSIGN(theinode.ul,  KBESTS(s, t, grammar->start_symbol)->KV[0]->lword);
	DUEXASSIGN(theinode.vl,  KBESTS(s, t, grammar->start_symbol)->KV[0]->rword);

	theinode.c=KBESTS(s, t, grammar->start_symbol)->KV[0]->prob; //w/o lm cost

#ifdef TRUECOST 
	double trg;
	trg=rootlmcost(theinode.ul, theinode.vl); 
	theinode.c+=trg;
#endif

	itemcount++; //newly added

	KBESTS(s, t, n)->Kand.push(theinode);//push into the priority queue for the candidates
      }
    }
    else{//non-root nodes
      
      int nbrruls=grammar->lhs_rule_table[n].size();
      for (int lhs_rules_idx=0; lhs_rules_idx<nbrruls; lhs_rules_idx++){
      //      for (r=0; r<grmr->B; r++){
      
	//	nl=grmr->R_tbl[0][r].rhsl;
	//	nr=grmr->R_tbl[0][r].rhsr;
	//	lhs=grmr->R_tbl[0][r].lhs;

	//	if (lhs!=n)
	//	  continue;

	Rule *rule=grammar->lhs_rule_table[n][lhs_rules_idx];

	nl = grammar->lhs_rule_table[n][lhs_rules_idx]->rhsl_int;
	nr = grammar->lhs_rule_table[n][lhs_rules_idx]->rhsr_int;

	if (nr < 0 )
	  continue; //non-bin rule

	//a matching bin rule
	//nl, nr, rule
	//all the rules that have n as the left hand side
	for (S=s+1; S<t; S++){ //all possible split points
	  lazyjthbest(s, S, nl, 1);
	  lazyjthbest(S, t, nr, 1);
	  
	  if (KBESTS(s, S, nl)->KV.size()>0 &&
	      KBESTS(S, t, nr)->KV.size()>0){//make sure the first bests are ready
	      
	    theinode.l=1;
	    theinode.r=1;
	    theinode.rul=rule;	   // the new rule data type
	    theinode.S=S;
	    DUEXASSIGN(theinode.ul,  KBESTS(s, S, nl)->KV[0]->lword);
	    DUEXASSIGN(theinode.vl,  KBESTS(s, S, nl)->KV[0]->rword);
	    DUEXASSIGN(theinode.ur,  KBESTS(S, t, nr)->KV[0]->lword);
	    DUEXASSIGN(theinode.vr,  KBESTS(S, t, nr)->KV[0]->rword);
	    theinode.c=KBESTS(s, S, nl)->KV[0]->prob +
	      KBESTS(S, t, nr)->KV[0]->prob + rule->prob; //w/o lm
	    //grmr->R_tbl[0][theinode.rul].prob; 

#ifdef TRUECOST
	    double trg;
	    if (theinode.rul->inverted)
	      trg = LMWEIGHT * compute_lm(theinode.ur, theinode.ul, theinode.vr, theinode.vl, theinode.rul, uchoice, vchoice);
	    else
	      trg = LMWEIGHT * compute_lm(theinode.ul, theinode.ur, theinode.vl, theinode.vr, theinode.rul, uchoice, vchoice);        
	      //lmcost(theinode.ul, theinode.vl, theinode.ur, theinode.vr, theinode.rul);
	    theinode.c+=trg;
#endif

	    itemcount++; //newly added
	    KBESTS(s, t, n)->Kand.push(theinode);
	  }
	}
      }//end of bin rules

      //if ((s==0) && (t==T))
	{//top level	, unary rules

	int nbrruls=grammar->lhs_rule_table[n].size();
	for (int lhs_rules_idx=0; lhs_rules_idx<nbrruls; lhs_rules_idx++){

	  //	for (r=0; r<grmr->U; r++){

	  //	  rhs=grmr->R_tbl[1][r].rhsl;
	  //	  lhs=grmr->R_tbl[1][r].lhs;

	  //	  if (lhs!=n)

	  //	    continue;

	  Rule *rule = grammar->lhs_rule_table[n][lhs_rules_idx];

	  rhs = grammar->lhs_rule_table[n][lhs_rules_idx]->rhsl_int;

	  nr = grammar->lhs_rule_table[n][lhs_rules_idx]->rhsr_int;
	  if (nr >= 0 )
	    continue; //bin rule


	  //a matching unary rule
	  //rhs, rule
	  // with the left hand side being n

	  lazyjthbest(s, t, rhs, 1);
	  if (KBESTS(s, t, rhs)->KV.size()>0){
	    theinode.l=1;
	    theinode.rul=rule;
	    DUEXASSIGN(theinode.ul,  KBESTS(s, t, rhs)->KV[0]->lword);
	    DUEXASSIGN(theinode.vl,  KBESTS(s, t, rhs)->KV[0]->rword);
	    theinode.c=KBESTS(s, t, rhs)->KV[0]->prob + 
	      rule->prob; //w/o lm
	      //grmr->R_tbl[1][theinode.rul].prob; 

	    //TRUECOST might involve lm cost in the case of general rules

	    itemcount++; //newly added
	    KBESTS(s, t, n)->Kand.push(theinode);
	  }
	}
      }//end of uni rules


    }//end if non-root node visited first time
  }



  //expansion
  int kbufsize=0;
  while ( (KBESTS(s, t, n)->KV.size() < j) &&
	  (KBESTS(s, t, n)->Kand.size() >0) ){
    //enforce beam...
    int kvsize=KBESTS(s, t, n)->KV.size();
    //    int kbufsize=KBESTS(s, t, n)->KV_buf.size();

    /*
    if (kvsize >0 && KBESTS(s, t, n)->KV[kvsize-1]->sita < KBESTS(s, t, n)->KV[0]->sita+LOGRATIOBEAM){
      break;
    }
    */
    //    if (kvsize > 10)
    //      break;
    //    if (kbufsize >0 && KBESTS(s, t, n)->KV_buf[kbufsize-1]->sita < KBESTS(s, t, n)->KV_buf[0]->sita+LOGRATIOBEAM){
    //      break;
    //    }
    
    if ( (kvsize>0 && KBESTS(s, t, n)->KV[kvsize-1]->prob < KBESTS(s, t, n)->KV[0]->prob + LOGRATIOBEAM) ||
	 (kbufsize >MAXKBUFSIZE) 
	 //||
	 //	 (KBESTS(s, t, n)->KV_buf.top()->sita > KBESTS(s, t, n)->bound) //early stopping
	 //|| 
	 //	 (kbufsize>0 && KBESTS(s, t, n)->KV_buf.back()->sita < KBESTS(s, t, n)->KV_buf.front()->sita +LOGRATIOBEAM))	 
	 )
      break;



    //POP-MIN
    kb_item_t inode=KBESTS(s, t, n)->Kand.top();
    KBESTS(s, t, n)->Kand.pop();

    bool updated=false;

    //push inode to buf, compute the combination cost, reranking...
    if ((s==0)&&(t==T)&&(n==grammar->_nonterminal_cnt)){//the root node
      pdd=KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1];

      double trg;

      trg=rootlmcost(inode.ul, inode.vl);
      //      trg=(TRIGRAM(-1, en[inode.ul[0]], en[inode.ul[1]])+TRIGRAM(en[inode.vl[1]], en[inode.vl[0]], -2))*LMWEIGHT;
      //      trg+=(BIGRAM(-1, en[inode.ul[0]]))*LMWEIGHT; //adding the leading bigram probability

      newsita=pdd->prob + trg;

      pd = dchart->cell(grammar->_nonterminal_cnt, 0, T, 0, 0, 0, 0); //should use this to UNIQUELY represent the best translation 
      //      pd=dcell(0, T, 0, 0, 0, 0, grmr->N); 

      oldsita=pd->prob;
      //      itemcount++;

      //inserted[0]?
      if (pd->inserted[0]!=1 || newsita>oldsita){
	if (pd->inserted[0]!=1)
	  pd->inserted[0]=1;

	pd->prob=newsita;
	pd->N = grammar->_nonterminal_cnt;
	pd->s = 0;
	pd->t = T;
	pd->rule = NULL; //top level

	//to be updated according to the new backpointers
	pd->lchild = pdd; 
	pd->rchild = NULL;
	
// 	DUEXASSIGN(pd->ul, inode.ul);
// 	DUEXASSIGN(pd->vl, inode.vl);
// 	DUEXASSIGN(pd->ur, inode.ul);
// 	DUEXASSIGN(pd->vr, inode.vl);

	DUEXASSIGN(pd->lword, inode.ul);
	DUEXASSIGN(pd->rword, inode.vl);

	//	if (oldsita==0)
	updated=true;
	//	pd->closed=1;
      }//end of updating viterbi
    }//end if the root node
    else{
      if (inode.rul->rhsr_int < 0){ //unary rule
      //      if ((s==0) && (t==T) && (n==grammar->start_symbol)){//top level	, unary rules

	//indexing into the right hand side
	pdd = KBESTS(s, t, inode.rul->rhsl_int)->KV[inode.l-1];

	Pr = inode.rul->prob;
	//	Pr=grmr->R_tbl[1][inode.rul].prob;

	newsita = Pr + pdd->prob;//log +

	//or 0, 1, 1 0///
	pd = dchart->cell(n, s, t, inode.ul[0], inode.ul[1], inode.vl[1], inode.vl[0]);
	//	pd=dcell(s, t, inode.ul[0], inode.ul[1], inode.vl[0], inode.vl[1], n);
	oldsita = pd->prob;

	//	itemcount++;
	//inserted ...
	if (pd->inserted[0]!=1 || newsita>oldsita){//maximizing
	  if (pd->inserted[0]!=1)
	    pd->inserted[0]=1;

	  pd->prob = newsita;
	  pd->N = n;
	  pd->s = s;
	  pd->t = t;
	  //	  pd->S=-1;
	  pd->rule = inode.rul;

	  pd->lchild = pdd;
	  pd->rchild = NULL;

	  //update accordingly
// 	  DUEXASSIGN(pd->ul, inode.ul);
// 	  DUEXASSIGN(pd->vl, inode.vl);
// 	  DUEXASSIGN(pd->ur, inode.ul);
// 	  DUEXASSIGN(pd->vr, inode.vl);

	  DUEXASSIGN(pd->lword, inode.ul);
	  DUEXASSIGN(pd->rword, inode.vl);

	  //	  if (oldsita==0)
	  updated=true;
	  //	  pd->closed=1;
	}//end of updating viterbi 
      }
      else{ //binary rules


	ITGDCell *leftcell = dchart->cell( inode.rul->rhsl_int, s, inode.S, inode.ul[0], inode.ul[1], inode.vl[1], inode.vl[0]);
	sita3 = leftcell->prob;
	//	sita3=sita(s, inode.S, inode.ul[0], inode.ul[1], inode.vl[0], inode.vl[1], grmr->R_tbl[0][inode.rul].rhsl);

	ITGDCell *rightcell = dchart->cell( inode.rul->rhsr_int, inode.S, t, inode.ur[0], inode.ur[1], inode.vr[1], inode.vr[0]); 
	sita0 = rightcell->prob;
	//	sita0=sita(inode.S, t, inode.ur[0], inode.ur[1], inode.vr[0], inode.vr[1], grmr->R_tbl[0][inode.rul].rhsr);

	sita30=sita3+sita0;//log+

	double trg;

	//needed, otherwise, uninitialized 
	uchoice[0]=uchoice[1]=0;
	vchoice[0]=vchoice[1]=0;

	if (inode.rul->inverted)
	  trg = LMWEIGHT * compute_lm( inode.ur, inode.ul, inode.vr, inode.vl, inode.rul, uchoice, vchoice);
	else
	  trg = LMWEIGHT * compute_lm( inode.ul, inode.ur, inode.vl, inode.vr, inode.rul, uchoice, vchoice);

	  
	pd = dchart->cell(n, s, t, uchoice[0], uchoice[1], vchoice[1], vchoice[0]);
	//	pd=dcell(s, t, uchoice[0], uchoice[1], vchoice[0], vchoice[1], n);
	  
	newsita = inode.rul->prob + sita30 + trg;
	//	newsita=grmr->R_tbl[0][inode.rul].prob+sita30+trg;

	oldsita = pd->prob;

	//	itemcount++;
	//inserted
	if (pd->inserted[0]!=1 || newsita>oldsita){//maximizing
	  if (pd->inserted[0]!=1)
	    pd->inserted[0]=1;

	  pd->prob = newsita;
	  pd->N = n;
	  pd->s = s;
	  pd->t = t;
	  //	  pd->S=inode.S;
	  pd->rule=inode.rul;
		    

// 	  DUEXASSIGN(pd->ul, inode.ul);
// 	  DUEXASSIGN(pd->vl, inode.vl);
// 	  DUEXASSIGN(pd->ur, inode.ur);
// 	  DUEXASSIGN(pd->vr, inode.vr);

	  pd->lchild = leftcell;
	  pd->rchild = rightcell;

	  DUEXASSIGN(pd->lword, uchoice);
	  DUEXASSIGN(pd->rword, vchoice);

	  //	  if (oldsita==0)
	  updated=true;
	  //	  pd->closed=1;
	}
	
      }//bin

    }//non-root

    //push to buf, sort
    //    if (updated)
    //    kbuf_item_t thekbuf_item;
    //    thekbuf_item.pd=pd;
    //    thekbuf_item.score=pd->sita;
    //    KBESTS(s, t, n)->KV_buf.push(pd);

    //push to buf, avoiding duplicates

    /*
    //sorted list implementation
    int bufsize=KBESTS(s, t, n)->KV_buf.size();
    //    int idx;
    kv_buf_t::iterator kv_idx;
    for (kv_idx=KBESTS(s, t, n)->KV_buf.begin(); kv_idx!=KBESTS(s, t, n)->KV_buf.end(); ++kv_idx){
      if ((*kv_idx)==pd)
	break;
    }
    if (kv_idx==KBESTS(s,t,n)->KV_buf.end())
      KBESTS(s, t, n)->KV_buf.push_back(pd);
    */

    /*
    if (KBESTS(s, t, n)->KV_buf_map[(long)pd]==0){
      KBESTS(s, t, n)->KV_buf_map[(long)pd]++;
      KBESTS(s, t, n)->KV_buf.push_back(pd);
    }
    */

    if (updated){
      KBESTS(s, t, n)->KV_buf.push(pd);
      //      KBESTS(s, t, n)->bound=inode.c;
    }
    kbufsize++; //no matter what, we increase the counter


    //push successors
    
    if ((s==0)&&(t==T)&&(n==grammar->_nonterminal_cnt)){//the root node 
      lazyjthbest(s, t, grammar->start_symbol, inode.l+1);

      if (KBESTS(s, t, grammar->start_symbol)->KV.size()>inode.l){//exists
	inode.l++;
	DUEXASSIGN(inode.ul,  KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1]->lword);
	DUEXASSIGN(inode.vl,  KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1]->rword);

	DUEXASSIGN(inode.ur,  KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1]->lword);
	DUEXASSIGN(inode.vr,  KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1]->rword);

	inode.c=KBESTS(s, t, grammar->start_symbol)->KV[inode.l-1]->prob;      

#ifdef TRUECOST
	double trg;
	trg = rootlmcost(inode.ul, inode.vl);
	inode.c += trg;
#endif

	itemcount++; //newly added
	KBESTS(s, t, n)->Kand.push(inode); //next item
      }

    }
    else{
      //      if ((s==0) && (t==T) && (n==grammar->start_symbol)){//top level	
      if (inode.rul->rhsr_int < 0){

	rhs = inode.rul->rhsl_int; 
	//	rhs=grmr->R_tbl[1][inode.rul].rhsl;

	lazyjthbest(s, t, rhs, inode.l+1);
	if (KBESTS(s, t, rhs)->KV.size()>inode.l){//exists
	  inode.l++;
	  DUEXASSIGN(inode.ul,  KBESTS(s, t, rhs)->KV[inode.l-1]->lword);
	  DUEXASSIGN(inode.vl,  KBESTS(s, t, rhs)->KV[inode.l-1]->rword);

	  DUEXASSIGN(inode.ur,  KBESTS(s, t, rhs)->KV[inode.l-1]->lword);
	  DUEXASSIGN(inode.vr,  KBESTS(s, t, rhs)->KV[inode.l-1]->rword);

	  inode.c = KBESTS(s, t, rhs)->KV[inode.l-1]->prob 
	    + inode.rul->prob; 
	    //+ grmr->R_tbl[1][inode.rul].prob;

	  itemcount++; //newly added

	  KBESTS(s, t, n)->Kand.push(inode); 
	}

      }
      else
	//TO BE CHANGED
	//	if (n!=grammar->T)	
	{ 
	  //bin rule

	  nl = inode.rul->rhsl_int;
	  //	  nl=grmr->R_tbl[0][inode.rul].rhsl;
	  nr = inode.rul->rhsr_int;
	  //	  nr=grmr->R_tbl[0][inode.rul].rhsr;
	  S=inode.S;

	  lazyjthbest(s, S, nl, inode.l+1);
	  //if successfully obtained, push to Kand
	  if (KBESTS(s, S, nl)->KV.size()>inode.l){//exists
	    inode.l++;
	    DUEXASSIGN(inode.ul, KBESTS(s, S, nl)->KV[inode.l-1]->lword);
	    DUEXASSIGN(inode.vl, KBESTS(s, S, nl)->KV[inode.l-1]->rword);
	
	    // keep the old r?
	    DUEXASSIGN(inode.ur, KBESTS(S, t, nr)->KV[inode.r-1]->lword);
	    DUEXASSIGN(inode.vr, KBESTS(S, t, nr)->KV[inode.r-1]->rword);
  
	    inode.c=KBESTS(s, S, nl)->KV[inode.l-1]->prob + 
	      KBESTS(S, t, nr)->KV[inode.r-1]->prob 
	      + inode.rul->prob; 
	      //+ grmr->R_tbl[0][inode.rul].prob;

#ifdef TRUECOST
	    double trg;

	    if (inode.rul->inverted)
	      trg = LMWEIGHT * compute_lm(inode.ur, inode.ul, inode.vr, inode.vl, inode.rul, uchoice, vchoice);
	    else
	      trg = LMWEIGHT * compute_lm(inode.ul, inode.ur, inode.vl, inode.vr, inode.rul, uchoice, vchoice);

	    //	    trg=lmcost(inode.ul, inode.vl, inode.ur, inode.vr, inode.rul);
	    inode.c += trg;
#endif

	    itemcount++; //newly added
	    KBESTS(s, t, n)->Kand.push(inode);
	    inode.l--; //backtrack
	  }

	  //	inode.l--; //backtrack
	  lazyjthbest(S, t, nr, inode.r+1);
	  //so is here
	  if (KBESTS(S, t, nr)->KV.size()>inode.r){//exists
	    inode.r++;

	    DUEXASSIGN(inode.ul, KBESTS(s, S, nl)->KV[inode.l-1]->lword);
	    DUEXASSIGN(inode.vl, KBESTS(s, S, nl)->KV[inode.l-1]->rword);

	    DUEXASSIGN(inode.ur, KBESTS(S, t, nr)->KV[inode.r-1]->lword);
	    DUEXASSIGN(inode.vr, KBESTS(S, t, nr)->KV[inode.r-1]->rword);
	  
	    inode.c = KBESTS(s, S, nl)->KV[inode.l-1]->prob + 
	      KBESTS(S, t, nr)->KV[inode.r-1]->prob 
	      + inode.rul->prob;
	      //+ grmr->R_tbl[0][inode.rul].prob;

#ifdef TRUECOST
	    double trg;

	    if (inode.rul->inverted)
	      trg = LMWEIGHT * compute_lm(inode.ur, inode.ul, inode.vr, inode.vl, inode.rul, uchoice, vchoice);
	    else
	      trg = LMWEIGHT * compute_lm(inode.ul, inode.ur, inode.vl, inode.vr, inode.rul, uchoice, vchoice);

	    //	    trg=lmcost(inode.ul, inode.vl, inode.ur, inode.vr, inode.rul);
	    inode.c+=trg;
#endif
	    itemcount++; //newly added

	    KBESTS(s, t, n)->Kand.push(inode);
	  }

	}//end of bin rules

    }//end if non-root

  }//keep processing til Kand is empty

  hash_map <long, int> lookup;

  /*
  //sort, scan through buf
  //  std::sort(KBESTS(s, t, n)->KV_buf.begin(), KBESTS(s, t, n)->KV_buf.end(), pdless);

  //enumeration of buf
  int totalbufsize=KBESTS(s,t,n)->KV_buf.size();
  //  int currtotal=0;

  kv_buf_t::iterator kv_i;
  for (kv_i=KBESTS(s,t,n)->KV_buf.end(); kv_i!=KBESTS(s,t,n)->KV_buf.begin(); --kv_i){
    //    ITGDCell *thepd=KBESTS(s, t, n)->KV_buf[i];
    ITGDCell *thepd=(*kv_i);
    KBESTS(s, t, n)->KV.push_back(thepd);
  }
  KBESTS(s, t, n)->KV_buf.clear();
  //  KBESTS(s, t, n)->KV_buf_map.clear();
  */


  //removing duplicates
  kv_buf_t temp_k_buf;

  int kvsize=KBESTS(s, t, n)->KV.size();
  for (int i=0; i<kvsize; i++){
    ITGDCell *thepd;
    thepd=KBESTS(s, t, n)->KV[i];

    if (lookup.find((long)thepd)==lookup.end()){
      lookup[(long)thepd]=1;

      temp_k_buf.push(thepd);
    }
  }

  KBESTS(s, t, n)->KV.clear();

  

  while (!KBESTS(s, t, n)->KV_buf.empty()){
    //    kbuf_item_t thekbuf;
    ITGDCell *thepd;

    thepd=KBESTS(s, t, n)->KV_buf.top();
    KBESTS(s, t, n)->KV_buf.pop();

    if (lookup.find((long)thepd)==lookup.end()){
      lookup[(long)thepd]=1;

      temp_k_buf.push(thepd);

    }

    //only trust the first half of the buf
    //    if (currtotal > totalbufsize/2)
    //      break;
  }
  lookup.clear();
  

  //refill
  
  while (!temp_k_buf.empty()){
    ITGDCell *thepd;

    thepd=temp_k_buf.top();
    temp_k_buf.pop();
    if (lookup.find((long)thepd)==lookup.end()){
      lookup[(long)thepd]=1;

      itemcount++; //newly added
      KBESTS(s, t, n)->KV.push_back(thepd);
    }
  }

  lookup.clear();
  
}



string CYKDecoder::topdowndecode(){
  ITGDCell *pd;
  //  DINT u[2], v[2];

  itemcount=0;

  //  lazyjthbest(0, T, grmr->N, 1);
  lazyjthbest(0, T, grammar->_nonterminal_cnt, 1);
  //  pd=KBESTS(0, T, grmr->N)->KV[0];
  pd=dchart->cell(grammar->_nonterminal_cnt, 0, T, 0, 0, 0, 0);
    //dcell(0, T, 0, 0, 0, 0, grmr->N); //should use this to UNIQUELY represent the best translation 

  pd->N = grammar->start_symbol;

  //  double logscore=pd->prob;

  //  DUEXASSIGN(u, pd->ul);
  //  DUEXASSIGN(v, pd->vl);

  //  pd=dcell(0, T, u[0], u[1], v[0], v[1], 0);


  double logscore=pd->prob; //under counting

  fprintf(logfile, "arcs popped %d\n", itemcount);
  fprintf(logfile, "log prob %.20lf\n", logscore);

  //  fprintf(fl, "arcs popped %d\n", itemcount);
  //  fprintf(fl, "log prob %.20lf\n", logscore);
  
  if (pd->prob > -INFINITY){
    return reconstruct(pd);
  }
  else
    return "";

  //  return reconstruct(0, T, pd);
}
   

