Beispiel #1
0
bool PreconditionedDownhillType::improve_energy(bool verbose) {
  iter++;
  const double old_energy = energy();
  const VectorXd g = pgrad();
  // Let's immediately free the cached gradient stored internally!
  invalidate_cache();
  // We waste some memory storing newx (besides *x itself), but this
  // avoids roundoff weirdness of trying to add nu*g back to *x, which
  // won't always get us back to the same value.
  Grid newx(gd, *x - nu*g);
  double newE = f.integral(kT, newx);
  int num_tries = 0;
  while (better(old_energy,newE)) {
    nu *= 0.5;
    newx = *x - nu*g;
    newE = f.integral(kT, newx);
    if (num_tries++ > 40) {
      printf("PreconditionedDownhill giving up after %d tries...\n", num_tries);
      return false; // It looks like we can't do any better with this algorithm.
    }
  }
  *x = newx;
  invalidate_cache();
  nu *= 1.1;
  if (verbose) {
    //lm->print_info();
    print_info();
  }
  return true;
}
boost::tuple< fit_tuple_t, fit_tuple_t >
find_grad( const fitness_f &f, const fit_tuple_t &current,
           const double x2, const double delta ) {
    // Declare our first and 2nd derivatives
    int psize = current.get<0>().size();
    int nsize = current.get<1>().size();
    vector_t pgrad( psize );
    vector_t ngrad( nsize );
    vector_t plapl( psize );
    vector_t nlapl( nsize );

    // Protons
    for ( int i = 0; i < psize; ++i ) {
        fit_tuple_t plus( current );
        fit_tuple_t minus( current );
        plus.get<0>()[i]  += delta;
        minus.get<0>()[i] -= delta;
        double x2plus  = f( plus );
        double x2minus = f( minus );
        pgrad[i] = ( x2plus - x2minus ) / ( 2 * delta );
        plapl[i] = ( x2plus + x2minus - 2 * x2 ) / bm::pow<2>(delta); }
    // Neutrons
    for ( int i = 0; i < nsize; ++i ) {
        fit_tuple_t plus( current );
        fit_tuple_t minus( current );
        plus.get<1>()[i]  += delta;
        minus.get<1>()[i] -= delta;
        double x2plus  = f( plus );
        double x2minus = f( minus );
        ngrad[i] = ( x2plus - x2minus ) / ( 2 * delta );
        nlapl[i] = ( x2plus + x2minus - 2 * x2 ) / bm::pow<2>(delta); }

    return boost::make_tuple( fit_tuple_t( pgrad, ngrad ),
                              fit_tuple_t( plapl, nlapl ) ); }
Beispiel #3
0
bool PreconditionedConjugateGradientType::improve_energy(bool verbose) {
  iter++;
  //printf("I am running ConjugateGradient::improve_energy\n");
  const double E0 = energy();
  if (E0 != E0) {
    // There is no point continuing, since we're starting with a NaN!
    // So we may as well quit here.
    if (verbose) {
      printf("The initial energy is a NaN, so I'm quitting early.\n");
      f.print_summary("has nan:", E0);
      fflush(stdout);
    }
    return false;
  }
  double beta;
  {
    // Note: my notation vaguely follows that of
    // [wikipedia](http://en.wikipedia.org/wiki/Nonlinear_conjugate_gradient_method).
    // I use the Polak-Ribiere method, with automatic direction reset.
    // Note that we could save some memory by using Fletcher-Reeves, and
    // it seems worth implementing that as an option for
    // memory-constrained problems (then we wouldn't need to store oldgrad).
    pgrad(); // compute pgrad first, since that computes both.
    beta = -pgrad().dot(-grad() - oldgrad)/oldgradsqr;
    oldgrad = -grad();
    if (beta < 0 || beta != beta || oldgradsqr == 0) beta = 0;
    if (verbose) printf("beta = %g\n", beta);
    oldgradsqr = -pgrad().dot(oldgrad);
    direction = -pgrad() + beta*direction;
    // Let's immediately free the cached gradient stored internally!
    invalidate_cache();
  } // free g and pg!

  const double gdotd = oldgrad.dot(direction);

  Minimizer lm = linmin(f, gd, kT, x, direction, -gdotd, &step);
  for (int i=0; i<100 && lm.improve_energy(verbose); i++) {
    if (verbose) lm.print_info("\t");
  }
  if (verbose) {
    //lm->print_info();
    print_info();
    printf("grad*dir/oldgrad*dir = %g\n", grad().dot(direction)/gdotd);
  }
  return (energy() < E0 || beta != 0);
}