statscore_t RandomDirectionOptimizer::TrueRun(Point& P) const
{
  statscore_t prevscore = P.GetScore();

  // do specified number of random direction optimizations
  unsigned int nrun = 0;
  unsigned int nrun_no_change = 0;
  for (; nrun_no_change < m_num_random_directions; nrun++, nrun_no_change++)
  {
    // choose a random direction in which to optimize
    Point direction;
    direction.Randomize();

    //find the minimum on the line
    statscore_t score = LineOptimize(P, direction, P);
    if (verboselevel() > 4) {
      cerr << "direction: " << direction << " => " << score;
      cerr << " (" <<  (score-prevscore) << ")" << endl;
      cerr << "\tending point: " <<  P << " => " << score << endl;
    }

    if (score-prevscore > kEPS)
      nrun_no_change = 0;
    prevscore = score;
  }

  if (verboselevel() > 2) {
    cerr << "end Powell Algo, nrun=" << nrun << endl;
  }
  return prevscore;
}
statscore_t Optimizer::Run(Point& P) const
{
  if (!m_feature_data) {
    cerr << "error trying to optimize without Features loaded" << endl;
    exit(2);
  }
  if (!m_scorer) {
    cerr << "error trying to optimize without a Scorer loaded" << endl;
    exit(2);
  }
  if (m_scorer->getReferenceSize() != m_feature_data->size()) {
    cerr << "error length mismatch between feature file and score file" << endl;
    exit(2);
  }

  P.SetScore(GetStatScore(P));

  if (verboselevel () > 2) {
    cerr << "Starting point: " << P << " => " << P.GetScore() << endl;
  }
  statscore_t score = TrueRun(P);

  // just in case its not done in TrueRun
  P.SetScore(score);
  if (verboselevel() > 2) {
    cerr << "Ending point: " << P << " => " << score << endl;
  }
  return score;
}
statscore_t SimpleOptimizer::TrueRun(Point& P) const
{
  statscore_t prevscore = 0;
  statscore_t bestscore = MIN_FLOAT;
  Point best;

  // If P is already defined and provides a score,
  // We must improve over this score.
  if (P.GetScore() > bestscore) {
    bestscore = P.GetScore();
    best = P;
  }

  int nrun = 0;
  do {
    ++nrun;
    if (verboselevel() > 2 && nrun > 1)
      cerr << "last diff=" << bestscore-prevscore << " nrun " << nrun << endl;
    prevscore = bestscore;

    Point  linebest;

    for (unsigned int d = 0; d < Point::getdim() + m_num_random_directions; d++) {
      if (verboselevel() > 4) {
        //	cerr<<"minimizing along direction "<<d<<endl;
        cerr << "starting point: " << P << " => " << prevscore << endl;
      }
      Point direction;
      if (d < Point::getdim()) { // regular updates along one dimension
        for (unsigned int i = 0; i < Point::getdim(); i++)
          direction[i]=0.0;
        direction[d]=1.0;
      }
      else { // random direction update
        direction.Randomize();
      }
      statscore_t curscore = LineOptimize(P, direction, linebest);//find the minimum on the line
      if (verboselevel() > 5) {
        cerr << "direction: " << d << " => " << curscore << endl;
        cerr << "\tending point: "<< linebest << " => " << curscore << endl;
      }
      if (curscore > bestscore) {
        bestscore = curscore;
        best = linebest;
        if (verboselevel() > 3) {
          cerr << "new best dir:" << d << " (" << nrun << ")" << endl;
          cerr << "new best Point " << best << " => "  << curscore << endl;
        }
      }
    }
    P = best; //update the current vector with the best point on all line tested
    if (verboselevel() > 3)
      cerr << nrun << "\t" << P << endl;
  } while (bestscore-prevscore > kEPS);

  if (verboselevel() > 2) {
    cerr << "end Powell Algo, nrun=" << nrun << endl;
    cerr << "last diff=" << bestscore-prevscore << endl;
    cerr << "\t" << P << endl;
  }
  return bestscore;
}