/* $Id: perceptron.cpp,v 1.2 2008/05/08 15:12:53 post Exp $
 *
 * Perceptron-based training for the ITG decoders.
 */

#include "itg.h"
#include "itgdec-cyk.h"
#include "itgparse.h"
#include "itggrmr.h"
#include "itgcorp.h"
#include "globals.h"
#include "feature.h"
using namespace std;

using viterbi::Parser;

int main(int argc, char* argv[]) {
  // load the parameters
  try {
    Globals::Load(argc, argv);
  } catch (Globals::load_error err) {
    cerr << "* FATAL: error processing parameters\n";
    cerr << "error message: " << err.text << endl;
    exit(1);
  }

  Globals* globals = Globals::Instance();

  LMWEIGHT = globals->get<double>("lm_weight");
  LOGRATIOBEAM = globals->get<double>("logratiobeam");
  MAXKBUFSIZE = globals->get<int>("maxkbufsize");

  string runid = globals->get<string>("runid");
  string rundir = globals->get<string>("rundir");
  if (chdir(rundir.data()))  {
    printf("* FATAL: couldn't chdir(%s)\n", rundir.data());
    exit(1);
  }

  //log file
  string namebuf = string(runid) + ".log";
  logfile = fopen(namebuf.data(), "w");
  if (NULL == logfile) {
    printf("* Fatal error: couldn't open logfile '%s'\n", namebuf.data());
    exit(-1);
  }
  setvbuf(logfile, (char *)NULL, _IONBF, 0);
//   printf("Logging to file %s\n", namebuf.data());

  // load the grammar
  string gramf = Globals::Get<string>("grammarfile");
  string probs = Globals::Get<string>("probfile");
  ITGGrammar* grammar = new ITGGrammar(gramf, probs);
  grammar->load();

  // setup the corpus
  string l1c = globals->get<string>("l1corpus");
  string l2c = globals->get<string>("l2corpus");
  ITGCorp* corpus;
  corpus = new ITGCorp((char *)l1c.data(), (char *)l2c.data(), globals->get<char>("runmode"));

  // create the ITG instance
  CYKDecoder* itg = new CYKDecoder(grammar, corpus);

  // load the weight vector
  weights.load(globals->get<string>("feature_file"));

  while (itg->sentence()) {
    // BOLD UPDATING (Liang et al. 2007)
    // 1. decode the sentence with k-best decoding (k=1 for now)
    itg->decode();
    FeatureList best = itg->topcell_->features;

    // 2. find the best alignment with the reference
    Parser parser(grammar, corpus);
    parser.viterbi();
    FeatureList ref = parser.topcell_->features;

    // 3. update
    weights = weights + ref - best;
  }
}
