1 //static const char* sccsid = "@(#)math_BFGS.cxx 3.2 95/01/10"; // Do not delete this line. Used by sccs.
4 #define No_Standard_RangeError
5 #define No_Standard_OutOfRange
6 #define No_Standard_DimensionError
9 #include <math_BFGS.ixx>
11 #include <math_BracketMinimum.hxx>
12 #include <math_BrentMinimum.hxx>
13 #include <math_FunctionWithDerivative.hxx>
14 #include <math_MultipleVarFunctionWithGradient.hxx>
15 #include <math_Matrix.hxx>
19 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
20 #define SIGN(a, b) ((b) > 0.0 ? fabs(a) : -fabs(a))
21 #define MOV3(a,b,c, d, e, f) (a)=(d); (b)= (e); (c)=(f);
24 // l'utilisation de math_BrentMinumim pur trouver un minimum dans une direction
25 // donnee n'est pas du tout optimale. voir peut etre interpolation cubique
26 // classique et aussi essayer "recherche unidimensionnelle economique"
27 // PROGRAMMATION MATHEMATIQUE (theorie et algorithmes) tome1 page 82.
29 class DirFunction : public math_FunctionWithDerivative {
35 math_MultipleVarFunctionWithGradient *F;
39 DirFunction(math_Vector& V1,
43 math_MultipleVarFunctionWithGradient& f) ;
45 void Initialize(const math_Vector& p0, const math_Vector& dir) const;
46 void TheGradient(math_Vector& Grad);
47 virtual Standard_Boolean Value(const Standard_Real x, Standard_Real& fval) ;
48 virtual Standard_Boolean Values(const Standard_Real x, Standard_Real& fval, Standard_Real& D) ;
49 virtual Standard_Boolean Derivative(const Standard_Real x, Standard_Real& D) ;
54 DirFunction::DirFunction(math_Vector& V1,
58 math_MultipleVarFunctionWithGradient& f) {
67 void DirFunction::Initialize(const math_Vector& p0,
68 const math_Vector& dir) const{
74 void DirFunction::TheGradient(math_Vector& Grad) {
79 Standard_Boolean DirFunction::Value(const Standard_Real x,
89 Standard_Boolean DirFunction::Values(const Standard_Real x,
96 F->Values(*P, fval, *G);
97 D = (*G).Multiplied(*Dir);
100 Standard_Boolean DirFunction::Derivative(const Standard_Real x,
107 F->Values(*P, fval, *G);
108 D = (*G).Multiplied(*Dir);
109 return Standard_True;
113 static Standard_Boolean MinimizeDirection(math_Vector& P,
117 Standard_Real& Result,
122 Standard_Real ax, xx, bx, Fax, Fxx, Fbx, F1;
123 F.Initialize(P, Dir);
125 Standard_Real dy1, Hnr1, lambda, alfa=0;
133 alfa = 0.7*(-F0)/dy1;
134 lambda = 0.015/Sqrt(Hnr1);
137 if (lambda > alfa) lambda = alfa;
139 math_BracketMinimum Bracket(F, 0.0, lambda, F0, F1);
140 if(Bracket.IsDone()) {
141 Bracket.Values(ax, xx, bx);
142 Bracket.FunctionValues(Fax, Fxx, Fbx);
144 Standard_Integer niter = 100;
145 Standard_Real tol = 1.e-03;
146 math_BrentMinimum Sol(tol, Fxx, niter, 1.e-08);
147 Sol.Perform(F, ax, xx, bx);
149 Standard_Real Scale = Sol.Location();
150 Result = Sol.Minimum();
153 return Standard_True;
156 return Standard_False;
160 void math_BFGS::Perform(math_MultipleVarFunctionWithGradient& F,
161 const math_Vector& StartingPoint) {
163 Standard_Boolean Good;
164 Standard_Integer n = TheLocation.Length();
165 Standard_Integer j, i;
166 Standard_Real fae, fad, fac;
168 math_Vector xi(1, n), dg(1, n), hdg(1, n);
169 math_Matrix hessin(1, n, 1, n);
172 math_Vector Temp1(1, n);
173 math_Vector Temp2(1, n);
174 math_Vector Temp3(1, n);
175 math_Vector Temp4(1, n);
176 DirFunction F_Dir(Temp1, Temp2, Temp3, Temp4, F);
178 TheLocation = StartingPoint;
179 Good = F.Values(TheLocation, PreviousMinimum, TheGradient);
181 Done = Standard_False;
182 TheStatus = math_FunctionError;
185 for(i = 1; i <= n; i++) {
187 xi(i) = -TheGradient(i);
191 for(nbiter = 1; nbiter <= Itermax; nbiter++) {
192 TheMinimum = PreviousMinimum;
193 Standard_Boolean IsGood = MinimizeDirection(TheLocation, TheMinimum,
195 xi, TheMinimum, F_Dir);
197 Done = Standard_False;
198 TheStatus = math_DirectionSearchError;
201 if(IsSolutionReached(F)) {
202 Done = Standard_True;
206 if (nbiter == Itermax) {
207 Done = Standard_False;
208 TheStatus = math_TooManyIterations;
211 PreviousMinimum = TheMinimum;
215 Good = F.Values(TheLocation, TheMinimum, TheGradient);
217 Done = Standard_False;
218 TheStatus = math_FunctionError;
222 for(i = 1; i <= n; i++) {
223 dg(i) = TheGradient(i) - dg(i);
225 for(i = 1; i <= n; i++) {
227 for (j = 1; j <= n; j++)
228 hdg(i) += hessin(i, j) * dg(j);
231 for(i = 1; i <= n; i++) {
232 fac += dg(i) * xi(i);
233 fae += dg(i) * hdg(i);
238 for(i = 1; i <= n; i++)
239 dg(i) = fac * xi(i) - fad * hdg(i);
241 for(i = 1; i <= n; i++)
242 for(j = 1; j <= n; j++)
243 hessin(i, j) += fac * xi(i) * xi(j)
244 - fad * hdg(i) * hdg(j) + fae * dg(i) * dg(j);
246 for(i = 1; i <= n; i++) {
248 for (j = 1; j <= n; j++) xi(i) -= hessin(i, j) * TheGradient(j);
251 Done = Standard_False;
252 TheStatus = math_TooManyIterations;
256 Standard_Boolean math_BFGS::IsSolutionReached(
257 math_MultipleVarFunctionWithGradient&) const {
259 return 2.0 * fabs(TheMinimum - PreviousMinimum) <=
260 XTol * (fabs(TheMinimum) + fabs(PreviousMinimum) + EPSZ);
263 math_BFGS::math_BFGS(math_MultipleVarFunctionWithGradient& F,
264 const math_Vector& StartingPoint,
265 const Standard_Real Tolerance,
266 const Standard_Integer NbIterations,
267 const Standard_Real ZEPS)
268 : TheLocation(1, StartingPoint.Length()),
269 TheGradient(1, StartingPoint.Length()) {
273 Itermax = NbIterations;
274 Perform(F, StartingPoint);
277 math_BFGS::math_BFGS(math_MultipleVarFunctionWithGradient& F,
278 const Standard_Real Tolerance,
279 const Standard_Integer NbIterations,
280 const Standard_Real ZEPS)
281 : TheLocation(1, F.NbVariables()),
282 TheGradient(1, F.NbVariables()) {
286 Itermax = NbIterations;
290 void math_BFGS::Delete()
293 void math_BFGS::Dump(Standard_OStream& o) const {
295 o<< "math_BFGS resolution: ";
297 o << " Status = Done \n";
298 o <<" Location Vector = " << Location() << "\n";
299 o <<" Minimum value = "<< Minimum()<<"\n";
300 o <<" Number of iterations = "<<NbIterations() <<"\n";;
303 o<< " Status = not Done because " << (Standard_Integer)TheStatus << "\n";