Ejemplo n.º 1
0
// Conjugate gradient optimization of function f, given its gradient gradf.
// Minimum is stored in min, its location in p. Tolerance is asked :
static void optigc(int dim, PnlVect *p, double tol, double *min,
                   double f(PnlVect *),
                   void gradf(PnlVect *, PnlVect *))
{
  int i, j;
  /* Scalars used to define directions */
  double        gg,gam,fp,dgg;  
  PnlVect   *g     = pnl_vect_create (dim); /* Auxiliary direction :
                                                     gradient at the minimum */
  PnlVect   *h     = pnl_vect_create (dim); /* Conjugate direction along
                                                     which to minimize */
  PnlVect   *grad  = pnl_vect_create (dim); /* Gradient */
  const int     ITMAX = 20000;
  const double  EPS   = 1.0e-18;

  fp=f(p);
  gradf(p,grad);

  pnl_vect_clone (h, grad);
  pnl_vect_clone (g, grad);
  pnl_vect_mult_double (h ,-1.0);
  pnl_vect_mult_double (g ,-1.0);
  pnl_vect_mult_double (grad ,-1.0);

  for(i=0; i<ITMAX; i++) {
    min1dir(dim,p,h,min,f); // Minimizing along direction h
    if(2.0*fabs((*min)-fp) <= tol*(fabs((*min))+fabs(fp)+EPS)) // Done : tolerance reached
      {
        pnl_vect_free (&g);
        pnl_vect_free (&h);
        pnl_vect_free (&grad);
        return;
      }
    fp=(*min);
    gradf(p,grad); // Computes gradient at point p, location of minimum
    dgg=gg=0.0;

    /* Computes coefficients applied to new direction for h */
    gg = pnl_vect_scalar_prod (g, g); /* Denominator */
    dgg = pnl_vect_scalar_prod (grad, grad) + pnl_vect_scalar_prod (g, grad); /* Numerator : Polak-Ribiere */

    if(gg==0.0) // Gradient equals zero : done
      {
        pnl_vect_free (&g);
        pnl_vect_free (&h);
        pnl_vect_free (&grad);
        return;
      }
    gam=dgg/gg;

    for(j=0; j<dim; j++){ // Defining directions for next iteration
      pnl_vect_set (g, j, - pnl_vect_get (grad,  j)); 
      pnl_vect_set (h, j, pnl_vect_get (g,  j)+gam * pnl_vect_get (h,  j));
    }
  }
  perror ("Too many iterations in optigc\n");
}
//Start Berechnung der Koordinaten
void ips::rechne()
{
    double richtung[3]={0};
    double schritt = 0.0;
    double x = start_x;
    double y = start_y;
    double z = start_z;
    double x_neu = 0.0;
    double y_neu = 0.0;
    double z_neu = 0.0;
    int i = 0;


    while(i<300)
    {
        //Grad (google it!!)
        gradf(x,y,z);
        richtung[0] = erg[0];
        richtung[1] = erg[1];
        richtung[2] = erg[2];
        //Schrittweite nach Armijo (google it!!)
        schritt = armijo(x,y,z);
        //qDebug() << schritt;
        x_neu = x - schritt*richtung[0];
        //qDebug() << x_neu;
        y_neu = y - schritt*richtung[1];
        z_neu = z - schritt*richtung[2];
        i++;

        //auf Staionaritaet pruefen
        if (((x-x_neu)*(x-x_neu)+(y-y_neu)*(y-y_neu)+(z-z_neu)*(z-z_neu))<0.0001)
        { break;}
        x = x_neu;
        y = y_neu;
        z = z_neu;

    }
    qDebug() << "Anzahl der Schleifen:" << i;

    if(i==300)
    {
        posx=0;
        posy=0;
        posz=0;
        qDebug()<< "Keine Annäherung in 300 Schritten möglich";
    }
    else
    {
        posx = x_neu;
        posy = y_neu;
        posz = z_neu;
    }
}