1 // Copyright (c) 1997-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #define No_Standard_RangeError
17 #define No_Standard_OutOfRange
18 #define No_Standard_DimensionError
22 #include <math_BFGS.hxx>
23 #include <math_BracketMinimum.hxx>
24 #include <math_BrentMinimum.hxx>
25 #include <math_FunctionWithDerivative.hxx>
26 #include <math_Matrix.hxx>
27 #include <math_MultipleVarFunctionWithGradient.hxx>
28 #include <Standard_DimensionError.hxx>
29 #include <StdFail_NotDone.hxx>
33 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
34 #define SIGN(a, b) ((b) > 0.0 ? fabs(a) : -fabs(a))
35 #define MOV3(a,b,c, d, e, f) (a)=(d); (b)= (e); (c)=(f);
38 // l'utilisation de math_BrentMinumim pur trouver un minimum dans une direction
39 // donnee n'est pas du tout optimale. voir peut etre interpolation cubique
40 // classique et aussi essayer "recherche unidimensionnelle economique"
41 // PROGRAMMATION MATHEMATIQUE (theorie et algorithmes) tome1 page 82.
43 class DirFunction : public math_FunctionWithDerivative {
49 math_MultipleVarFunctionWithGradient *F;
53 DirFunction(math_Vector& V1,
57 math_MultipleVarFunctionWithGradient& f) ;
59 void Initialize(const math_Vector& p0, const math_Vector& dir) const;
60 void TheGradient(math_Vector& Grad);
61 virtual Standard_Boolean Value(const Standard_Real x, Standard_Real& fval) ;
62 virtual Standard_Boolean Values(const Standard_Real x, Standard_Real& fval, Standard_Real& D) ;
63 virtual Standard_Boolean Derivative(const Standard_Real x, Standard_Real& D) ;
68 DirFunction::DirFunction(math_Vector& V1,
72 math_MultipleVarFunctionWithGradient& f) {
81 void DirFunction::Initialize(const math_Vector& p0,
82 const math_Vector& dir) const{
88 void DirFunction::TheGradient(math_Vector& Grad) {
93 Standard_Boolean DirFunction::Value(const Standard_Real x,
100 return Standard_True;
103 Standard_Boolean DirFunction::Values(const Standard_Real x,
110 F->Values(*P, fval, *G);
111 D = (*G).Multiplied(*Dir);
112 return Standard_True;
114 Standard_Boolean DirFunction::Derivative(const Standard_Real x,
121 F->Values(*P, fval, *G);
122 D = (*G).Multiplied(*Dir);
123 return Standard_True;
127 static Standard_Boolean MinimizeDirection(math_Vector& P,
131 Standard_Real& Result,
136 Standard_Real ax, xx, bx, Fax, Fxx, Fbx, F1;
137 F.Initialize(P, Dir);
139 Standard_Real dy1, Hnr1, lambda, alfa=0;
143 alfa = 0.7*(-F0)/dy1;
144 lambda = 0.015/Sqrt(Hnr1);
147 if (lambda > alfa) lambda = alfa;
149 math_BracketMinimum Bracket(F, 0.0, lambda, F0, F1);
150 if(Bracket.IsDone()) {
151 Bracket.Values(ax, xx, bx);
152 Bracket.FunctionValues(Fax, Fxx, Fbx);
154 Standard_Integer niter = 100;
155 Standard_Real tol = 1.e-03;
156 math_BrentMinimum Sol(tol, Fxx, niter, 1.e-08);
157 Sol.Perform(F, ax, xx, bx);
159 Standard_Real Scale = Sol.Location();
160 Result = Sol.Minimum();
163 return Standard_True;
166 return Standard_False;
170 void math_BFGS::Perform(math_MultipleVarFunctionWithGradient& F,
171 const math_Vector& StartingPoint) {
173 Standard_Boolean Good;
174 Standard_Integer n = TheLocation.Length();
175 Standard_Integer j, i;
176 Standard_Real fae, fad, fac;
178 math_Vector xi(1, n), dg(1, n), hdg(1, n);
179 math_Matrix hessin(1, n, 1, n);
182 math_Vector Temp1(1, n);
183 math_Vector Temp2(1, n);
184 math_Vector Temp3(1, n);
185 math_Vector Temp4(1, n);
186 DirFunction F_Dir(Temp1, Temp2, Temp3, Temp4, F);
188 TheLocation = StartingPoint;
189 Good = F.Values(TheLocation, PreviousMinimum, TheGradient);
191 Done = Standard_False;
192 TheStatus = math_FunctionError;
195 for(i = 1; i <= n; i++) {
197 xi(i) = -TheGradient(i);
201 for(nbiter = 1; nbiter <= Itermax; nbiter++) {
202 TheMinimum = PreviousMinimum;
203 Standard_Boolean IsGood = MinimizeDirection(TheLocation, TheMinimum,
205 xi, TheMinimum, F_Dir);
207 Done = Standard_False;
208 TheStatus = math_DirectionSearchError;
211 if(IsSolutionReached(F)) {
212 Done = Standard_True;
216 if (nbiter == Itermax) {
217 Done = Standard_False;
218 TheStatus = math_TooManyIterations;
221 PreviousMinimum = TheMinimum;
225 Good = F.Values(TheLocation, TheMinimum, TheGradient);
227 Done = Standard_False;
228 TheStatus = math_FunctionError;
232 for(i = 1; i <= n; i++) {
233 dg(i) = TheGradient(i) - dg(i);
235 for(i = 1; i <= n; i++) {
237 for (j = 1; j <= n; j++)
238 hdg(i) += hessin(i, j) * dg(j);
241 for(i = 1; i <= n; i++) {
242 fac += dg(i) * xi(i);
243 fae += dg(i) * hdg(i);
248 for(i = 1; i <= n; i++)
249 dg(i) = fac * xi(i) - fad * hdg(i);
251 for(i = 1; i <= n; i++)
252 for(j = 1; j <= n; j++)
253 hessin(i, j) += fac * xi(i) * xi(j)
254 - fad * hdg(i) * hdg(j) + fae * dg(i) * dg(j);
256 for(i = 1; i <= n; i++) {
258 for (j = 1; j <= n; j++) xi(i) -= hessin(i, j) * TheGradient(j);
261 Done = Standard_False;
262 TheStatus = math_TooManyIterations;
266 Standard_Boolean math_BFGS::IsSolutionReached(
267 math_MultipleVarFunctionWithGradient&) const {
269 return 2.0 * fabs(TheMinimum - PreviousMinimum) <=
270 XTol * (fabs(TheMinimum) + fabs(PreviousMinimum) + EPSZ);
273 math_BFGS::math_BFGS(const Standard_Integer NbVariables,
274 const Standard_Real Tolerance,
275 const Standard_Integer NbIterations,
276 const Standard_Real ZEPS)
277 : TheLocation(1, NbVariables),
278 TheGradient(1, NbVariables) {
282 Itermax = NbIterations;
286 math_BFGS::~math_BFGS()
290 void math_BFGS::Dump(Standard_OStream& o) const {
292 o<< "math_BFGS resolution: ";
294 o << " Status = Done \n";
295 o <<" Location Vector = " << Location() << "\n";
296 o <<" Minimum value = "<< Minimum()<<"\n";
297 o <<" Number of iterations = "<<NbIterations() <<"\n";;
300 o<< " Status = not Done because " << (Standard_Integer)TheStatus << "\n";