// 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; } }