Path: blob/devel/ElmerGUI/netgen/libsrc/opti/bfgs.cpp
3206 views
/***************************************************************************/1/* */2/* Vorlesung Optimierung I, Gfrerer, WS94/95 */3/* BFGS-Verfahren zur L�sung freier nichtlinearer Optimierungsprobleme */4/* */5/* Programmautor: Joachim Sch�berl */6/* Matrikelnummer: 9155284 */7/* */8/***************************************************************************/910#include <mystdlib.h>11#include <myadt.hpp>1213#include <linalg.hpp>14#include "opti.hpp"151617namespace netgen18{1920void Cholesky (const DenseMatrix & a,21DenseMatrix & l, Vector & d)22{23// Factors A = L D L^T2425double x;2627int i, j, k;28int n = a.Height();2930// (*testout) << "a = " << a << endl;3132l = a;3334for (i = 1; i <= n; i++)35{36for (j = i; j <= n; j++)37{38x = l.Get(i, j);3940for (k = 1; k < i; k++)41x -= l.Get(i, k) * l.Get(j, k) * d.Get(k);4243if (i == j)44{45d.Elem(i) = x;46}47else48{49l.Elem(j, i) = x / d.Get(k);50}51}52}5354for (i = 1; i <= n; i++)55{56l.Elem(i, i) = 1;57for (j = i+1; j <= n; j++)58l.Elem(i, j) = 0;59}6061/*62// Multiply:63(*testout) << "multiplied factors: " << endl;64for (i = 1; i <= n; i++)65for (j = 1; j <= n; j++)66{67x = 0;68for (k = 1; k <= n; k++)69x += l.Get(i, k) * l.Get(j, k) * d.Get(k);70(*testout) << x << " ";71}72(*testout) << endl;73*/74}757677void MultLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)78{79/*80int i, j, n;81double val;8283n = l.Height();84p = g;85for (i = 1; i <= n; i++)86{87val = 0;88for (j = i; j <= n; j++)89val += p.Get(j) * l.Get(j, i);90p.Set(i, val);91}92for (i = 1; i <= n; i++)93p.Elem(i) *= d.Get(i);9495for (i = n; i >= 1; i--)96{97val = 0;98for (j = 1; j <= i; j++)99val += p.Get(j) * l.Get(i, j);100p.Set(i, val);101}102*/103104105106double val;107108int n = l.Height();109p = g;110111for (int i = 0; i < n; i++)112{113val = 0;114for (int j = i; j < n; j++)115val += p(j) * l(j, i);116p(i) = val;117}118119for (int i = 0; i < n; i++)120p(i) *= d(i);121122for (int i = n-1; i >= 0; i--)123{124val = 0;125for (int j = 0; j <= i; j++)126val += p(j) * l(i, j);127p(i) = val;128}129}130131void SolveLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)132{133double val;134135int n = l.Height();136p = g;137138for (int i = 0; i < n; i++)139{140val = 0;141for (int j = 0; j < i; j++)142val += p(j) * l(i,j);143p(i) -= val;144}145146for (int i = 0; i < n; i++)147p(i) /= d(i);148149for (int i = n-1; i >= 0; i--)150{151val = 0;152for (int j = i+1; j < n; j++)153val += p(j) * l(j, i);154p(i) -= val;155}156}157158int LDLtUpdate (DenseMatrix & l, Vector & d, double a, const Vector & u)159{160// Bemerkung: Es wird a aus R erlaubt161// Rueckgabewert: 0 .. D bleibt positiv definit162// 1 .. sonst163164int i, j, n;165166n = l.Height();167168Vector v(n);169double t, told, xi;170171told = 1;172v = u;173174for (j = 1; j <= n; j++)175{176t = told + a * sqr (v.Elem(j)) / d.Get(j);177178if (t <= 0)179{180(*testout) << "update err, t = " << t << endl;181return 1;182}183184xi = a * v.Elem(j) / (d.Get(j) * t);185186d.Elem(j) *= t / told;187188for (i = j + 1; i <= n; i++)189{190v.Elem(i) -= v.Elem(j) * l.Elem(i, j);191l.Elem(i, j) += xi * v.Elem(i);192}193194told = t;195}196197return 0;198}199200201double BFGS (202Vector & x, // i: Startwert203// o: Loesung, falls IFAIL = 0204const MinFunction & fun,205const OptiParameters & par,206double eps207)208209210{211int i, j, n = x.Size();212long it;213char a1crit, a3acrit;214215216Vector d(n), g(n), p(n), temp(n), bs(n), xneu(n), y(n), s(n), x0(n);217DenseMatrix l(n);218DenseMatrix hesse(n);219220double /* normg, */ alphahat, hd, fold;221double a1, a2;222const double mu1 = 0.1, sigma = 0.1, xi1 = 1, xi2 = 10;223const double tau = 0.1, tau1 = 0.1, tau2 = 0.6;224225Vector typx(x.Size()); // i: typische Groessenordnung der Komponenten226double f, f0;227double typf; // i: typische Groessenordnung der Loesung228double fmin = -1e5; // i: untere Schranke fuer Funktionswert229// double eps = 1e-8; // i: Abbruchschranke fuer relativen Gradienten230double tauf = 0.1; // i: Abbruchschranke fuer die relative Aenderung der231// Funktionswerte232int ifail; // o: 0 .. Erfolg233// -1 .. Unterschreitung von fmin234// 1 .. kein Erfolg bei Liniensuche235// 2 .. �berschreitung von itmax236237typx = par.typx;238typf = par.typf;239240241l = 0;242for (i = 1; i <= n; i++)243l.Elem(i, i) = 1;244245f = fun.FuncGrad (x, g);246f0 = f;247x0 = x;248249it = 0;250do251{252// Restart253254if (it % (5 * n) == 0)255{256257for (i = 1; i <= n; i++)258d.Elem(i) = typf/ sqr (typx.Get(i)); // 1;259for (i = 2; i <= n; i++)260for (j = 1; j < i; j++)261l.Elem(i, j) = 0;262263/*264hesse = 0;265for (i = 1; i <= n; i++)266hesse.Elem(i, i) = typf / sqr (typx.Get(i));267268fun.ApproximateHesse (x, hesse);269270Cholesky (hesse, l, d);271*/272}273274it++;275if (it > par.maxit_bfgs)276{277ifail = 2;278break;279}280281282// Solve with factorized B283284SolveLDLt (l, d, g, p);285286// (*testout) << "l " << l << endl287// << "d " << d << endl288// << "g " << g << endl289// << "p " << p << endl;290291292p *= -1;293y = g;294295fold = f;296297// line search298299alphahat = 1;300lines (x, xneu, p, f, g, fun, par, alphahat, fmin,301mu1, sigma, xi1, xi2, tau, tau1, tau2, ifail);302303if(ifail == 1)304(*testout) << "no success with linesearch" << endl;305306/*307// if (it > par.maxit_bfgs/2)308{309(*testout) << "x = " << x << endl;310(*testout) << "xneu = " << xneu << endl;311(*testout) << "f = " << f << endl;312(*testout) << "g = " << g << endl;313}314*/315316// (*testout) << "it = " << it << " f = " << f << endl;317// if (ifail != 0) break;318319s.Set2 (1, xneu, -1, x);320y *= -1;321y.Add (1,g); // y += g;322323x = xneu;324325// BFGS Update326327MultLDLt (l, d, s, bs);328329a1 = y * s;330a2 = s * bs;331332if (a1 > 0 && a2 > 0)333{334if (LDLtUpdate (l, d, 1 / a1, y) != 0)335{336cerr << "BFGS update error1" << endl;337(*testout) << "BFGS update error1" << endl;338(*testout) << "l " << endl << l << endl339<< "d " << d << endl;340ifail = 1;341break;342}343344if (LDLtUpdate (l, d, -1 / a2, bs) != 0)345{346cerr << "BFGS update error2" << endl;347(*testout) << "BFGS update error2" << endl;348(*testout) << "l " << endl << l << endl349<< "d " << d << endl;350ifail = 1;351break;352}353}354355// Calculate stop conditions356357hd = eps * max2 (typf, fabs (f));358a1crit = 1;359for (i = 1; i <= n; i++)360if ( fabs (g.Elem(i)) * max2 (typx.Elem(i), fabs (x.Elem(i))) > hd)361a1crit = 0;362363364a3acrit = (fold - f <= tauf * max2 (typf, fabs (f)));365366// testout << "g = " << g << endl;367// testout << "a1crit, a3crit = " << int(a1crit) << ", " << int(a3acrit) << endl;368369/*370// Output for tests371372normg = sqrt (g * g);373374testout << "it =" << setw (5) << it375<< " f =" << setw (12) << setprecision (5) << f376<< " |g| =" << setw (12) << setprecision (5) << normg;377378testout << " x = (" << setw (12) << setprecision (5) << x.Elem(1);379for (i = 2; i <= n; i++)380testout << "," << setw (12) << setprecision (5) << x.Elem(i);381testout << ")" << endl;382*/383384//(*testout) << "it = " << it << " f = " << f << " x = " << x << endl385// << " g = " << g << " p = " << p << endl << endl;386387// (*testout) << "|g| = " << g.L2Norm() << endl;388389if (g.L2Norm() < fun.GradStopping (x)) break;390391}392while (!a1crit || !a3acrit);393394/*395(*testout) << "it = " << it << " g = " << g << " f = " << f396<< " fail = " << ifail << endl;397*/398if (f0 < f || (ifail == 1))399{400(*testout) << "fail, f = " << f << " f0 = " << f0 << endl;401f = f0;402x = x0;403}404405// (*testout) << "x = " << x << ", x0 = " << x0 << endl;406return f;407}408409}410411412