C#, Cálculo Numérico - Método de cálculo y programa fuente de Métodos Cuasi-Newton o Métricos Variables en Multidimensiones
1 Métodos cuasi-Newton (métrica variable)
Los métodos cuasi-Newton intentan generar una estimación de la inversa de la matriz de Hesse.
. Luego se utiliza para determinar el siguiente punto de iteración.
El gradiente en la región alrededor de a está dado por
En el mínimo el gradiente es cero.
por lo tanto, el mejor siguiente paso de dirección viene dado por
El algoritmo BFGS (`Broyden-Fletcher-Goldfarb-Shanno') se basa en esta técnica.
2 programa fuente C#
usando Sistema;
namespace Legalsoft.Truffer
{ /// <summary> /// Métodos de métricas variables o cuasi-Newton en multidimensiones /// </summary> public class QuasiNewton { public static void dfpmin(double[] p, double gtol, ref int iter , ref doble traste, función RealValueFunWithDiff) { const int ITMAX = 200; const doble EPS = float.Epsilon; //numeric_limits<doble>.epsilon(); constante doble TOLX = 4 * EPS; constante doble STPMX = 100,0;
verificación bool = falso;
int n = p.Longitud;
doble[] dg = nuevo doble[n];
doble[] g = nuevo doble[n];
doble[] hdg = nuevo doble[n];
doble[] pnew = nuevo doble[n];
doble[] xi = nuevo doble[n];
doble[,] hessin = nuevo doble[n, n];
doble fp = funcd.funk(p);
funcd.df(p,g);
doble suma = 0,0;
para (int i = 0; i < n; i++)
{ para (int j = 0; j < n; j++) { hessin[i, j] = 0.0; } hessin[i, i] = 1,0; xi[i] = -g[i]; suma += p[i] * p[i]; } doble stpmax = STPMX * Math.Max(Math.Sqrt(suma), (doble)n); for (int su = 0; su < ITMAX; su++) { iter = su; Roots.lnsrch(p, fp, g, xi, pnew, ref fret, stpmax, ref check, funcd); fp = traste;
for (int i = 0; i < n; i++)
{ xi[i] = pnew[i] - p[i]; p[i] = pnuevo[i]; } prueba doble = 0,0; for (int i = 0; i < n; i++) { doble temperatura = Math.Abs(xi[i]) / Math.Max(Math.Abs(p[i]), 1.0); if (temperatura > prueba) { prueba = temperatura; } } if (prueba < TOLX) { retorno; }
for (int i = 0; i < n; i++)
{ dg[i] = g[i]; }
funcd.df(p,g);
prueba = 0,0;
doble guarida = Math.Max(Math.Abs(traste), 1.0);
for (int i = 0; i < n; i++)
{ doble temperatura = Math.Abs(g[i]) * Math.Max(Math.Abs(p[i]), 1.0) / den; if (temperatura > prueba) { prueba = temperatura; } } if (prueba < gtol) { retorno; } for (int i = 0; i < n; i++) { dg[i] = g[i] - dg[i]; }
for (int i = 0; i < n; i++)
{ hdg[i] = 0.0; for (int j = 0; j < n; j++) { hdg[i] += hessin[i, j] * dg[j]; } } doble cara = 0.0; doble fae = 0,0; suma doble = 0,0; doble sumaxi = 0,0; for (int i = 0; i < n; i++) { fac += dg[i] * xi[i]; fae += dg[i] * hdg[i]; sumdg += Globals.SQR(dg[i]);
sumxi += Globals.SQR(xi[i]);
}
if (fac > Math.Sqrt(EPS * sumdg * sumxi))
{ fac = 1.0 / fac; doble moda = 1,0 / fae; for (int i = 0; i < n; i++) { dg[i] = fac * xi[i] - moda * hdg[i]; } for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { hessin[i, j] += fac * xi[i] * xi[j] - moda * hdg[i] * hdg[j] + fae * dg[i] * dg[j];
hessin[j, i] = hessin[i, j];
}
}
}
for (int i = 0; i < n; i++)
{ xi[i] = 0.0; for (int j = 0; j < n; j++) { xi[i] -= hessin[i, j] * g[j]; } } } throw new Exception("demasiadas iteraciones en dfpmin"); } } }