Buscamos programación experta en lenguaje C
Recetas Numéricas en C
El libro y programa adjunto tienen procedimientos completos. Sin embargo, encapsulé su versión C++, que puede encontrar el valor extremo de uno o varios parámetros. El archivo de encabezado completo es:
#ifndef __OPTIMIZATION_H__
#define __OPTIMIZATION_H__
.//////////////////////////////////////////////// /// ////////////////////////////
// clase TOptimización
/ /
// $ Encuentra el valor mínimo de uno o más parámetros de la función
//
// Esta clase optimiza un parámetro de forma predeterminada. , solo necesita ingresar el número de parámetros de optimización
// Se puede utilizar para optimizar la función objetivo.
//
// ...El código principal proviene de:
// Recetas Numéricas en C++
// El El arte de la informática científica
// Segunda edición
// William H. Press Saul A. Teukolsky
// William T. Vetterling Brian P. Flannery
//
// Traducción al chino:
// Algoritmo numérico C++ (segunda edición) Traducido por Hu Jianwei, Zhao Zhiyong, Xue Yunhua y otros p>
// Electronics Industrial Press Beijing (2005)
//
// Autor: Jian Feng
// Correo electrónico: fengj@tom .com
// 9 de diciembre de 2006
//
////////////////// //////// /////////////////////////////////////////// //////////
//
// Función de entrada:
//
// @ MaxIterationStep: Número máximo de iteraciones, predeterminado 1000
// @ParameterNumbers: Número de parámetros de optimización, predeterminado 1
// @InitMatrix: Parámetros de matriz de inicialización (N*N), predeterminado
// @Tolerance: Tolerancia permitida, por defecto 1E-7
//
// Función de ejecución:
//
// @ExecutePowell: use el método powell para la optimización de múltiples parámetros
// @ExecuteBrent: use el método brent para la optimización de un solo parámetro
// p>
// Función de salida:
//
// @OptimizatedParameters: datos del resultado de la optimización
// @ObjectiveFunctionValue: el valor de función objetivo en el valor optimizado
// p>
// Ejemplo de uso:
//
// 1. Parámetro único
// doble objfun(doble a){ p>
// doble suma = 0;
// for(int i = 0; i < DataPoints; + +i)
// suma += SQR( Exps[i] - Theo(a));
// }
// valor doble
// TOptimización opt;
// if(opt.ExecuteBrent(objfun, -10, -1)) opt.OptimizatedParameters(&value);
/ /
// 2. Múltiples parámetros
// double objfun(double *a){
// double sum = 0;
// for(int i = 0; i +i) // suma += SQR(Exps[i] - Theo(a)); // } // valor doble[ 3] // TOoptimización opt(3); // double ival[3] = {-1, 0, 1}; // if(opt.ExecutePowell(objfun, ival)) opt.OptimizatedParameters(value); // espacio de nombres{ static int ncom; Variables static double *pcom_p; //Variables públicas static double *xicom_p; //Variables públicas static double (*nrfunc)(double*) ; //Puntero de función pública } clase TOptimización { privado: typedef double ( *Reff)(doble *); typedef doble (*Ptrf)(doble ); público: TOptimización(int n = 1); ~TOptimization(){ FreeMemory(); } //Método principal void ParameterNumbers(int n){ FreeMemory(); (); } //Utiliza el método Powell para optimizar uno o más parámetros bool ExecutePowell(Reff obj, double *a = 0); // Utilice el método brent para optimizar un parámetro, y se debe proporcionar el intervalo donde se encuentra el parámetro bool ExecuteBrent(Ptrf obj, double vFrom = 0, double vTo = 1); void OptimizatedParameters (double *a){ for(int i=0; i void OptimizatedParameters(double &a ){ a = vmin; } //void OptimizatedParameters(double *a){ // if(método) for(int i=0; i // else *a = vmin; //} //Otros métodos p> void InitMatrix(doble **m) { for(int i=0; i for(int j = 0 ; j matx[i][j]=m[i][j] setm = true; } > void MaxIterationStep(int s){ ITMAX = s } void Tolerance(double eps){ ftol = eps } double ObjectiveFunctionValue()const{ return trast; /p> privado: double brent(doble hacha, doble bx, doble cx, Ptrf f, doble tol, doble &xmin, int &flag); void mnbrak( doble &ax, doble &bx, doble &cx, doble &fa, doble &fb, doble &fc, función Ptrf); void linmin(doble *p, doble *xi, doble &fret, función Reff); bool powell(doble *p, doble **xi, doble ftol, int &iter, doble &fret, función Reff); void shft2(doble &a, doble &b, const doble c){ a=b; b=c; } void shft3(doble &a, doble &b, doble &c, const doble d){ a=b; b=c; doble SQR(doble x){ return x * x } void SWAP(doble &a, doble &b){ double dum=a; b=dum; > doble SIGNO(const doble &a, const doble &b){return b >= 0?(a>=0?a:-a):(a>=0?-a:a);} double MAX(const double &a, const double &b){return b > a ? (b): (a);} void AllocateMemory(); void FreeMemory(); static double f1dim(double x) { int j; double *xt = new double [ ncom]; //Vec_Dp &pcom=*pcom_p,&xicom=*xicom_p; doble *pcom = pcom_p, *xicom = xicom_p para ( j=0;j xt[j]=pcom[j]+x*xicom[j]; //eliminar []xt; p> doble val = nrfunc(xt); eliminar []xt; return val; } bool setm //Si establecer la matriz inicial de la dirección de optimización int num ; //Parámetros de optimización int ITMAX; //Número máximo de iteraciones int iter; //Número real de pasos de iteración int método; //Método de optimización 0: 1-D brent, 2: M-D Powell double vmin; //Parámetros de optimización unidimensionales double ftol; p> double fret ; //Valor de la función objetiva double *coef; //Valor del parámetro de optimización multidimensional double **matx; -dirección del parámetro de optimización dimensional }; ///////////////////////////// ////////////// ///////////////////////////////////// TOptimización en línea::TOptimización(int n ) { num = n; ftol = 1e-7; p> ITMAX = 1000; iter = 0; traste = 0.; vmin = 0.; método = 0; setm = false; AllocateMemory(); } optimización nula en línea::AllocateMemory() { pcom_p = nuevo doble [num]; xicom_p = nuevo doble [num]; coef = nuevo doble [ num]; matx = nuevo doble *[ num]; for(int i = 0; i < num; ++i) { coef[i] = 0.; p> matx[i] = nuevo doble [num]; for(int j = 0; j < num; ++j) matx[i][ j]=(i == j ? 1.0 : 0.0 } } inline void TOptimization::FreeMemory() { for(int i = 0; i < num; ++i) { eliminar []matx[i]; } eliminar []matx; eliminar []pcom_p; p> eliminar []xicom_p; eliminar []coef; } inline bool TOptimización::ExecutePowell(Reff obj, doub le *a) { método = 1; if(a) for(int i = 0; i < num; ++i) coef[i] = a[i]; return powell(coef, matx, ftol, iter, traste, obj); } inline bool TOptimization::ExecuteBrent(Ptrf obj, double vFrom, double vTo) { método = 0; int flag; doble cx, fa, fb, fc; mnbrak(vFrom,vTo,cx,fa,fb,fc,obj); traste = brent( vFrom,vTo,cx,obj, ftol,vmin, flag); return flag ? true : false; } TOptimización nula en línea::mnbrak (doble &ax, doble &bx, doble &cx, doble &fa, doble &fb, doble &fc, función Ptrf) { const double GOLD=1.618034, GLIMIT=100.0,TINY=1.0e-20; doble ulim,u,r,q,fu; fa=func(ax); fb=func(bx); if (fb > fa) { INTERCAMBIAR(ax,bx); INTERCAMBIAR(fb,fa); } cx=bx+GOLD*(bx-ax); fc=func(cx); mientras (fb > fc) { r=(bx-ax)*(fb-fc); q=(bx-cx)*(fb-fa); u=bx-((bx-cx)*q-(bx-ax)*r)/ (2.0*SIGN(MAX(fabs(q-r),TINY),q-r)) ; ulim=bx+GLIMIT*(cx-bx); if ((bx-u)*(u-cx) > 0.0) { fu=func(u); if (fu < fc) { ax=bx; bx=u; fa=fb; fb=fu; return; } else if (fu > fb) { cx= u; fc=fu; return; } u=cx+GOLD*(cx-bx); fu=func(u); } else if ((cx-u)*(u-ulim) > 0.0) { fu=func(u); if (fu < fc) { shft3(bx,cx,u,cx+GOLD*(cx-bx)); shft3(fb,fc, fu,func(u)); } } else if ((u-ulim)*(ulim-cx) >= 0.0) { u=ulim; fu=func(u); } else { u=cx+GOLD*(cx-bx); fu=func(u); } shft3(ax,bx,cx,u); shft3(fa,fb, fc,fu); } } optimización doble en línea::brent(doble hacha, doble bx, doble cx, Ptrf f, doble tol, doble &xmin, int &flag) { flag = 1; const double CGOLD=0.3819660; const doble ZEPS=1.0e-20; int iter; doble a,b,d=0.0,etemp,fu,fv,fw,fx; doble p,q,r,tol1,tol2,u,v,w,x,xm; doble e=0.0; a=(ax < cx ? ax : cx); b=(ax > cx ? ax : cx); x=w=v=bx; fw=fv =fx=f(x); for (iter=0;iter xm=0.5*(a+b); tol2=2.0*(tol1=tol*fabs(x)+ZEPS); if (fabs(x-xm) <= (tol2-0.5*(b-a))) { xmin=x; return fx; } if (fabs(e) > tol1) { r=(x-w)*(fx-fv); q=(x-v)*(fx-fw); p=(x-v)*q-(x-w)* r; q=2.0*(q-r); si (q > 0.0) p = -p; q=fabs(q); etemp=e; e=d; if (fabs(p) >= fabs(0.5*q*etemp) || p < ;= q*(a-x) || p >= q*(b-x)) d=CGOLD*(e=(x >= xm ? a-x : b-x)); else { d=p/q; u=x+d; if (u-a < tol2 || b-u < tol2) d=SIGN(tol1,xm-x); } } más { d=CGOLD*(e=(x > = xm ? a-x : b-x)); } u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d)); fu=f(u); if (fu <= fx) { if (u >= x) a=x else b=x; ; shft3(v,w,x,u); shft3(fv,fw,fx,fu); } más { if (u < x) a=u; else b=u; if (fu <= fw || w == x) { v=w ; w=u; fv=fw; fw=fu; } else if (fu <= fv | | v == x || v == w) { v=u; fv=fu; } } } bandera = 0; xmin=x; retorno fx; } Optimización void en línea::linmin(double *p, double *xi, double &fret, Reff func) { int j, flag; const double TOL=1.0e-8; double xx,xmin,fx,fb,fa,bx,ax; int n=num; ncom=n; //pcom_p=nuevo Vec_Dp(n); //xicom_p=nuevo Vec_Dp(n); nrfunc =func; //Vec_Dp &pcom=*pcom_p,&xicom=*xicom_p; doble *pcom = pcom_p, *xicom = xicom_p; para ( j=0;j pcom[j]=p[j]; xicom[j]=xi[j]; } ax=0.0; xx=1.0; mnbrak(ax,xx,bx,fa,fx,fb,f1dim); es et=brent(ax,xx,bx,f1dim,TOL,xmin, flag); for (j=0;j xi[j] *= xmin; p[j] += xi[j]; } //eliminar xicom_p; / /delete pcom_p; } inline bool TOptimización::powell(double *p, double **xi, double ftol, int &iter, double &fret , función Reff) { const int ITMAX=500; const double TINY=1.0e-20; int i ,j,ibig; double del,fp,fptt,t; int n=num; //Vec_Dp pt(n),ptt( n),xit(n); doble *pt, *ptt, *xit; for(i = 0; i < n; ++i) { pt = nuevo doble [n]; ptt = nuevo doble [n]; xit = nuevo doble [n]; } traste=func(p); for (j=0;j for (iter=0;;++iter) { fp=traste; ibig=0; del= 0.0; para (i=0;i para (j=0;j fptt=traste; linmin(p,xit,traste,func); if (fptt-traste > del) { del=fptt-fret; ibig=i+1; } } if ( 2.0*(fp-traste) <= ftol*(fabs(fp)+fabs(traste))+TINY) { eliminar []pt; eliminar []ptt; eliminar []xit; devolver verdadero; } if (iter == ITMAX) { eliminar []pt; eliminar []ptt; eliminar []xit; devolver falso; p> //cerr<<"powell excede el máximo de iteraciones."; p> } for (j=0;j ptt[j]=2.0*p[j]-pt[j]; xit[j]=p[j]-pt[j]; pt[j]=p[j]; } fptt=func(ptt); if (fptt < fp) { t=2.0*(fp-2.0*traste+fptt)*SQR(fp-traste-del )-del*SQR(fp-fptt); if (t < 0.0) { linmin(p,xit,fret,func); for (j=0;j xi[j][ibig-1]=xi[j][n-1]; xi[j ][n-1]=salir[j]; } } } } } #endif