Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/opti/bfgs.cpp
3206 views
1
/***************************************************************************/
2
/* */
3
/* Vorlesung Optimierung I, Gfrerer, WS94/95 */
4
/* BFGS-Verfahren zur L�sung freier nichtlinearer Optimierungsprobleme */
5
/* */
6
/* Programmautor: Joachim Sch�berl */
7
/* Matrikelnummer: 9155284 */
8
/* */
9
/***************************************************************************/
10
11
#include <mystdlib.h>
12
#include <myadt.hpp>
13
14
#include <linalg.hpp>
15
#include "opti.hpp"
16
17
18
namespace netgen
19
{
20
21
void Cholesky (const DenseMatrix & a,
22
DenseMatrix & l, Vector & d)
23
{
24
// Factors A = L D L^T
25
26
double x;
27
28
int i, j, k;
29
int n = a.Height();
30
31
// (*testout) << "a = " << a << endl;
32
33
l = a;
34
35
for (i = 1; i <= n; i++)
36
{
37
for (j = i; j <= n; j++)
38
{
39
x = l.Get(i, j);
40
41
for (k = 1; k < i; k++)
42
x -= l.Get(i, k) * l.Get(j, k) * d.Get(k);
43
44
if (i == j)
45
{
46
d.Elem(i) = x;
47
}
48
else
49
{
50
l.Elem(j, i) = x / d.Get(k);
51
}
52
}
53
}
54
55
for (i = 1; i <= n; i++)
56
{
57
l.Elem(i, i) = 1;
58
for (j = i+1; j <= n; j++)
59
l.Elem(i, j) = 0;
60
}
61
62
/*
63
// Multiply:
64
(*testout) << "multiplied factors: " << endl;
65
for (i = 1; i <= n; i++)
66
for (j = 1; j <= n; j++)
67
{
68
x = 0;
69
for (k = 1; k <= n; k++)
70
x += l.Get(i, k) * l.Get(j, k) * d.Get(k);
71
(*testout) << x << " ";
72
}
73
(*testout) << endl;
74
*/
75
}
76
77
78
void MultLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)
79
{
80
/*
81
int i, j, n;
82
double val;
83
84
n = l.Height();
85
p = g;
86
for (i = 1; i <= n; i++)
87
{
88
val = 0;
89
for (j = i; j <= n; j++)
90
val += p.Get(j) * l.Get(j, i);
91
p.Set(i, val);
92
}
93
for (i = 1; i <= n; i++)
94
p.Elem(i) *= d.Get(i);
95
96
for (i = n; i >= 1; i--)
97
{
98
val = 0;
99
for (j = 1; j <= i; j++)
100
val += p.Get(j) * l.Get(i, j);
101
p.Set(i, val);
102
}
103
*/
104
105
106
107
double val;
108
109
int n = l.Height();
110
p = g;
111
112
for (int i = 0; i < n; i++)
113
{
114
val = 0;
115
for (int j = i; j < n; j++)
116
val += p(j) * l(j, i);
117
p(i) = val;
118
}
119
120
for (int i = 0; i < n; i++)
121
p(i) *= d(i);
122
123
for (int i = n-1; i >= 0; i--)
124
{
125
val = 0;
126
for (int j = 0; j <= i; j++)
127
val += p(j) * l(i, j);
128
p(i) = val;
129
}
130
}
131
132
void SolveLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p)
133
{
134
double val;
135
136
int n = l.Height();
137
p = g;
138
139
for (int i = 0; i < n; i++)
140
{
141
val = 0;
142
for (int j = 0; j < i; j++)
143
val += p(j) * l(i,j);
144
p(i) -= val;
145
}
146
147
for (int i = 0; i < n; i++)
148
p(i) /= d(i);
149
150
for (int i = n-1; i >= 0; i--)
151
{
152
val = 0;
153
for (int j = i+1; j < n; j++)
154
val += p(j) * l(j, i);
155
p(i) -= val;
156
}
157
}
158
159
int LDLtUpdate (DenseMatrix & l, Vector & d, double a, const Vector & u)
160
{
161
// Bemerkung: Es wird a aus R erlaubt
162
// Rueckgabewert: 0 .. D bleibt positiv definit
163
// 1 .. sonst
164
165
int i, j, n;
166
167
n = l.Height();
168
169
Vector v(n);
170
double t, told, xi;
171
172
told = 1;
173
v = u;
174
175
for (j = 1; j <= n; j++)
176
{
177
t = told + a * sqr (v.Elem(j)) / d.Get(j);
178
179
if (t <= 0)
180
{
181
(*testout) << "update err, t = " << t << endl;
182
return 1;
183
}
184
185
xi = a * v.Elem(j) / (d.Get(j) * t);
186
187
d.Elem(j) *= t / told;
188
189
for (i = j + 1; i <= n; i++)
190
{
191
v.Elem(i) -= v.Elem(j) * l.Elem(i, j);
192
l.Elem(i, j) += xi * v.Elem(i);
193
}
194
195
told = t;
196
}
197
198
return 0;
199
}
200
201
202
double BFGS (
203
Vector & x, // i: Startwert
204
// o: Loesung, falls IFAIL = 0
205
const MinFunction & fun,
206
const OptiParameters & par,
207
double eps
208
)
209
210
211
{
212
int i, j, n = x.Size();
213
long it;
214
char a1crit, a3acrit;
215
216
217
Vector d(n), g(n), p(n), temp(n), bs(n), xneu(n), y(n), s(n), x0(n);
218
DenseMatrix l(n);
219
DenseMatrix hesse(n);
220
221
double /* normg, */ alphahat, hd, fold;
222
double a1, a2;
223
const double mu1 = 0.1, sigma = 0.1, xi1 = 1, xi2 = 10;
224
const double tau = 0.1, tau1 = 0.1, tau2 = 0.6;
225
226
Vector typx(x.Size()); // i: typische Groessenordnung der Komponenten
227
double f, f0;
228
double typf; // i: typische Groessenordnung der Loesung
229
double fmin = -1e5; // i: untere Schranke fuer Funktionswert
230
// double eps = 1e-8; // i: Abbruchschranke fuer relativen Gradienten
231
double tauf = 0.1; // i: Abbruchschranke fuer die relative Aenderung der
232
// Funktionswerte
233
int ifail; // o: 0 .. Erfolg
234
// -1 .. Unterschreitung von fmin
235
// 1 .. kein Erfolg bei Liniensuche
236
// 2 .. �berschreitung von itmax
237
238
typx = par.typx;
239
typf = par.typf;
240
241
242
l = 0;
243
for (i = 1; i <= n; i++)
244
l.Elem(i, i) = 1;
245
246
f = fun.FuncGrad (x, g);
247
f0 = f;
248
x0 = x;
249
250
it = 0;
251
do
252
{
253
// Restart
254
255
if (it % (5 * n) == 0)
256
{
257
258
for (i = 1; i <= n; i++)
259
d.Elem(i) = typf/ sqr (typx.Get(i)); // 1;
260
for (i = 2; i <= n; i++)
261
for (j = 1; j < i; j++)
262
l.Elem(i, j) = 0;
263
264
/*
265
hesse = 0;
266
for (i = 1; i <= n; i++)
267
hesse.Elem(i, i) = typf / sqr (typx.Get(i));
268
269
fun.ApproximateHesse (x, hesse);
270
271
Cholesky (hesse, l, d);
272
*/
273
}
274
275
it++;
276
if (it > par.maxit_bfgs)
277
{
278
ifail = 2;
279
break;
280
}
281
282
283
// Solve with factorized B
284
285
SolveLDLt (l, d, g, p);
286
287
// (*testout) << "l " << l << endl
288
// << "d " << d << endl
289
// << "g " << g << endl
290
// << "p " << p << endl;
291
292
293
p *= -1;
294
y = g;
295
296
fold = f;
297
298
// line search
299
300
alphahat = 1;
301
lines (x, xneu, p, f, g, fun, par, alphahat, fmin,
302
mu1, sigma, xi1, xi2, tau, tau1, tau2, ifail);
303
304
if(ifail == 1)
305
(*testout) << "no success with linesearch" << endl;
306
307
/*
308
// if (it > par.maxit_bfgs/2)
309
{
310
(*testout) << "x = " << x << endl;
311
(*testout) << "xneu = " << xneu << endl;
312
(*testout) << "f = " << f << endl;
313
(*testout) << "g = " << g << endl;
314
}
315
*/
316
317
// (*testout) << "it = " << it << " f = " << f << endl;
318
// if (ifail != 0) break;
319
320
s.Set2 (1, xneu, -1, x);
321
y *= -1;
322
y.Add (1,g); // y += g;
323
324
x = xneu;
325
326
// BFGS Update
327
328
MultLDLt (l, d, s, bs);
329
330
a1 = y * s;
331
a2 = s * bs;
332
333
if (a1 > 0 && a2 > 0)
334
{
335
if (LDLtUpdate (l, d, 1 / a1, y) != 0)
336
{
337
cerr << "BFGS update error1" << endl;
338
(*testout) << "BFGS update error1" << endl;
339
(*testout) << "l " << endl << l << endl
340
<< "d " << d << endl;
341
ifail = 1;
342
break;
343
}
344
345
if (LDLtUpdate (l, d, -1 / a2, bs) != 0)
346
{
347
cerr << "BFGS update error2" << endl;
348
(*testout) << "BFGS update error2" << endl;
349
(*testout) << "l " << endl << l << endl
350
<< "d " << d << endl;
351
ifail = 1;
352
break;
353
}
354
}
355
356
// Calculate stop conditions
357
358
hd = eps * max2 (typf, fabs (f));
359
a1crit = 1;
360
for (i = 1; i <= n; i++)
361
if ( fabs (g.Elem(i)) * max2 (typx.Elem(i), fabs (x.Elem(i))) > hd)
362
a1crit = 0;
363
364
365
a3acrit = (fold - f <= tauf * max2 (typf, fabs (f)));
366
367
// testout << "g = " << g << endl;
368
// testout << "a1crit, a3crit = " << int(a1crit) << ", " << int(a3acrit) << endl;
369
370
/*
371
// Output for tests
372
373
normg = sqrt (g * g);
374
375
testout << "it =" << setw (5) << it
376
<< " f =" << setw (12) << setprecision (5) << f
377
<< " |g| =" << setw (12) << setprecision (5) << normg;
378
379
testout << " x = (" << setw (12) << setprecision (5) << x.Elem(1);
380
for (i = 2; i <= n; i++)
381
testout << "," << setw (12) << setprecision (5) << x.Elem(i);
382
testout << ")" << endl;
383
*/
384
385
//(*testout) << "it = " << it << " f = " << f << " x = " << x << endl
386
// << " g = " << g << " p = " << p << endl << endl;
387
388
// (*testout) << "|g| = " << g.L2Norm() << endl;
389
390
if (g.L2Norm() < fun.GradStopping (x)) break;
391
392
}
393
while (!a1crit || !a3acrit);
394
395
/*
396
(*testout) << "it = " << it << " g = " << g << " f = " << f
397
<< " fail = " << ifail << endl;
398
*/
399
if (f0 < f || (ifail == 1))
400
{
401
(*testout) << "fail, f = " << f << " f0 = " << f0 << endl;
402
f = f0;
403
x = x0;
404
}
405
406
// (*testout) << "x = " << x << ", x0 = " << x0 << endl;
407
return f;
408
}
409
410
}
411
412