Adjusting testing case due to changes in algorithm behavior.
[occt.git] / src / math / math_FunctionSetRoot.cxx
CommitLineData
b311480e 1// Copyright (c) 1997-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15// pmn 15/05/97 pas de Gauss avec des pivot trop petit. SVD fait mieux
16// l'affaire + limitation de la longeur du pas + qq comentaire issus d'EUCLID3
17// pmn 10/06/97 refonte totale du traitement des bords + ajustement des init
18// et des tolerances pour brent...
19
0797d9d3 20//#ifndef OCCT_DEBUG
7fd59977 21#define No_Standard_RangeError
22#define No_Standard_OutOfRange
23#define No_Standard_DimensionError
24//#endif
25
26//math_FunctionSetRoot.cxx
27
28
29#include <math_FunctionSetRoot.ixx>
30#include <Standard_DimensionError.hxx>
31#include <math_Gauss.hxx>
32#include <math_SVD.hxx>
33#include <math_GaussLeastSquare.hxx>
34#include <math_IntegerVector.hxx>
35#include <math_Function.hxx>
36#include <math_BrentMinimum.hxx>
37#include <math_FunctionSetWithDerivatives.hxx>
38#include <Precision.hxx>
39
40
41//===========================================================================
42// - A partir d une solution de depart, recherche d une direction.( Newton la
43// plupart du temps, gradient si Newton echoue.
7fd59977 44// - Recadrage au niveau des bornes avec recalcul de la direction si une
45// inconnue a une valeur imposee.
7fd59977 46// -Si On ne sort pas des bornes
47// Tant que (On ne progresse pas assez ou on ne change pas de direction)
48// . Si (Progression encore possible)
49// Si (On ne sort pas des bornes)
50// On essaye de progresser dans cette meme direction.
51// Sinon
52// On diminue le pas d'avancement ou on change de direction.
53// Sinon
54// Si on depasse le minimum
55// On fait une interpolation parabolique.
7fd59977 56// - Si on a progresse sur F
57// On fait les tests d'arret
58// Sinon
59// On change de direction
60//============================================================================
61
3e42bd70
J
62#define FSR_DEBUG(arg)
63// Uncomment the following code to have debug output to cout
89d8607f 64//==========================================================
65//static Standard_Boolean mydebug = Standard_True;
66//#undef FSR_DEBUG
67//#define FSR_DEBUG(arg) {if (mydebug) { cout << arg << endl; }}
68//===========================================================
fbadd2cc 69
7fd59977 70class MyDirFunction : public math_Function
71{
72
89d8607f 73 math_Vector *P0;
74 math_Vector *Dir;
75 math_Vector *P;
76 math_Vector *FV;
77 math_FunctionSetWithDerivatives *F;
7fd59977 78
79public :
80
89d8607f 81 MyDirFunction(math_Vector& V1,
82 math_Vector& V2,
83 math_Vector& V3,
84 math_Vector& V4,
85 math_FunctionSetWithDerivatives& f) ;
86
87 void Initialize(const math_Vector& p0, const math_Vector& dir) const;
88 //For hp :
89 Standard_Boolean Value(const math_Vector& Sol, math_Vector& FF,
90 math_Matrix& DF, math_Vector& GH,
91 Standard_Real& F2, Standard_Real& Gnr1);
92 // Standard_Boolean MyDirFunction::Value(const math_Vector& Sol, math_Vector& FF,
93 // math_Matrix& DF, math_Vector& GH,
94 // Standard_Real& F2, Standard_Real& Gnr1);
95 Standard_Boolean Value(const Standard_Real x, Standard_Real& fval) ;
96
7fd59977 97};
98
99MyDirFunction::MyDirFunction(math_Vector& V1,
89d8607f 100 math_Vector& V2,
101 math_Vector& V3,
102 math_Vector& V4,
103 math_FunctionSetWithDerivatives& f) {
104
105 P0 = &V1;
106 Dir = &V2;
107 P = &V3;
108 FV = &V4;
109 F = &f;
7fd59977 110}
111
112void MyDirFunction::Initialize(const math_Vector& p0,
89d8607f 113 const math_Vector& dir) const
7fd59977 114{
115 *P0 = p0;
116 *Dir = dir;
117}
118
119
120Standard_Boolean MyDirFunction::Value(const Standard_Real x,
89d8607f 121 Standard_Real& fval)
7fd59977 122{
123 Standard_Real p;
124 for(Standard_Integer i = P->Lower(); i <= P->Upper(); i++) {
125 p = Dir->Value(i);
126 P->Value(i) = p * x + P0->Value(i);
127 }
128 if( F->Value(*P, *FV) ) {
129
130 Standard_Real aVal = 0.;
131
132 for(Standard_Integer i = FV->Lower(); i <= FV->Upper(); i++) {
133 aVal = FV->Value(i);
134 if(aVal < 0.) {
89d8607f 135 if(aVal <= -1.e+100) // Precision::HalfInfinite() later
136 // if(Precision::IsInfinite(Abs(FV->Value(i)))) {
137 // fval = Precision::Infinite();
138 return Standard_False;
7fd59977 139 }
140 else if(aVal >= 1.e+100) // Precision::HalfInfinite() later
89d8607f 141 return Standard_False;
7fd59977 142 }
143
144 fval = 0.5 * (FV->Norm2());
145 return Standard_True;
146 }
147 return Standard_False;
148}
149
150Standard_Boolean MyDirFunction::Value(const math_Vector& Sol,
89d8607f 151 math_Vector& FF,
152 math_Matrix& DF,
153 math_Vector& GH,
154 Standard_Real& F2,
155 Standard_Real& Gnr1)
7fd59977 156{
157 if( F->Values(Sol, FF, DF) ) {
158
159 Standard_Real aVal = 0.;
160
161 for(Standard_Integer i = FF.Lower(); i <= FF.Upper(); i++) {
89d8607f 162 // modified by NIZHNY-MKK Mon Oct 3 17:56:50 2005.BEGIN
7fd59977 163 aVal = FF.Value(i);
164 if(aVal < 0.) {
89d8607f 165 if(aVal <= -1.e+100) // Precision::HalfInfinite() later
166 // if(Precision::IsInfinite(Abs(FF.Value(i)))) {
167 // F2 = Precision::Infinite();
168 // Gnr1 = Precision::Infinite();
169 return Standard_False;
7fd59977 170 }
171 else if(aVal >= 1.e+100) // Precision::HalfInfinite() later
89d8607f 172 return Standard_False;
173 // modified by NIZHNY-MKK Mon Oct 3 17:57:05 2005.END
7fd59977 174 }
175
176
177 F2 = 0.5 * (FF.Norm2());
178 GH.TMultiply(DF, FF);
12f139fd 179 for(Standard_Integer i = GH.Lower(); i <= GH.Upper(); i++)
180 {
181 if(Precision::IsInfinite((GH.Value(i))))
182 {
183 return Standard_False;
184 }
185 }
7fd59977 186 Gnr1 = GH.Norm2();
187 return Standard_True;
188 }
189 return Standard_False;
190}
191
192
193//--------------------------------------------------------------
194static Standard_Boolean MinimizeDirection(const math_Vector& P0,
89d8607f 195 const math_Vector& P1,
196 const math_Vector& P2,
197 const Standard_Real F1,
198 math_Vector& Delta,
199 const math_Vector& Tol,
200 MyDirFunction& F)
201 // Purpose : minimisation a partir de 3 points
202 //-------------------------------------------------------
7fd59977 203{
204 // (1) Evaluation d'un tolerance parametrique 1D
205 Standard_Real tol1d = 2.1 , invnorme, tsol;
206 Standard_Real Eps = 1.e-16;
207 Standard_Real ax, bx, cx;
208
209 for (Standard_Integer ii =1; ii<=Tol.Length(); ii++) {
210 invnorme = Abs(Delta(ii));
211 if (invnorme>Eps) tol1d = Min(tol1d, Tol(ii) / invnorme);
212 }
213 if (tol1d > 1.9) return Standard_False; //Pas la peine de se fatiguer
214 tol1d /= 3;
215
89d8607f 216 //JR/Hp :
7fd59977 217 math_Vector PP0 = P0 ;
218 math_Vector PP1 = P1 ;
219 Delta = PP1 - PP0;
89d8607f 220 // Delta = P1 - P0;
7fd59977 221 invnorme = Delta.Norm();
222 if (invnorme <= Eps) return Standard_False;
223 invnorme = ((Standard_Real) 1) / invnorme;
224
225 F.Initialize(P1, Delta);
226
227 // (2) On minimise
3e42bd70 228 FSR_DEBUG (" minimisation dans la direction")
89d8607f 229 ax = -1; bx = 0;
7fd59977 230 cx = (P2-P1).Norm()*invnorme;
231 if (cx < 1.e-2) return Standard_False;
232 math_BrentMinimum Sol(F, ax, bx, cx, tol1d, 100, tol1d);
233 if(Sol.IsDone()) {
234 tsol = Sol.Location();
235 if (Sol.Minimum() < F1) {
236 Delta.Multiply(tsol);
237 return Standard_True;
238 }
239 }
240 return Standard_False;
241}
242
243//----------------------------------------------------------------------
244static Standard_Boolean MinimizeDirection(const math_Vector& P,
89d8607f 245 math_Vector& Dir,
246 const Standard_Real& PValue,
247 const Standard_Real& PDirValue,
248 const math_Vector& Gradient,
249 const math_Vector& DGradient,
250 const math_Vector& Tol,
251 MyDirFunction& F)
252 // Purpose: minimisation a partir de 2 points et une derives
253 //----------------------------------------------------------------------
7fd59977 254
255{
256 // (0) Evaluation d'un tolerance parametrique 1D
257 Standard_Boolean good = Standard_False;
258 Standard_Real Eps = 1.e-20;
259 Standard_Real tol1d = 1.1, Result = PValue, absdir;
260
261 for (Standard_Integer ii =1; ii<=Tol.Length(); ii++) {
262 absdir = Abs(Dir(ii));
263 if (absdir >Eps) tol1d = Min(tol1d, Tol(ii) / absdir);
264 }
265 if (tol1d > 0.9) return Standard_False;
89d8607f 266
7fd59977 267 // (1) On realise une premiere interpolation quadratique
268 Standard_Real ax, bx, cx, df1, df2, Delta, tsol, fsol, tsolbis;
89d8607f 269 FSR_DEBUG(" essai d interpolation");
fbadd2cc 270
7fd59977 271 df1 = Gradient*Dir;
272 df2 = DGradient*Dir;
273
274 if (df1<-Eps && df2>Eps) { // cuvette
275 tsol = - df1 / (df2 - df1);
276 }
277 else {
278 cx = PValue;
279 bx = df1;
280 ax = PDirValue - (bx+cx);
281
282 if (Abs(ax) <= Eps) { // cas lineaire
283 if ((Abs(bx) >= Eps)) tsol = - cx/bx;
284 else tsol = 0;
285 }
286 else { // cas quadratique
287 Delta = bx*bx - 4*ax*cx;
288 if (Delta > 1.e-9) {
89d8607f 289 // il y a des racines, on prend la plus proche de 0
290 Delta = Sqrt(Delta);
291 tsol = -(bx + Delta);
292 tsolbis = (Delta - bx);
293 if (Abs(tsolbis) < Abs(tsol)) tsol = tsolbis;
294 tsol /= 2*ax;
7fd59977 295 }
296 else {
89d8607f 297 // pas ou peu de racine : on "extremise"
298 tsol = -(0.5*bx)/ax;
7fd59977 299 }
300 }
301 }
302
303 if (Abs(tsol) >= 1) return Standard_False; //resultat sans interet
304
305 F.Initialize(P, Dir);
306 F.Value(tsol, fsol);
307
308 if (fsol<PValue) {
309 good = Standard_True;
310 Result = fsol;
89d8607f 311 FSR_DEBUG("t= "<<tsol<<" F = " << fsol << " OldF = "<<PValue);
7fd59977 312 }
313
314 // (2) Si l'on a pas assez progresser on realise une recherche
315 // en bonne et due forme, a partir des inits precedents
316 if ((fsol > 0.2*PValue) && (tol1d < 0.5)) {
89d8607f 317
7fd59977 318 if (tsol <0) {
319 ax = tsol; bx = 0.0; cx = 1.0;
320 }
321 else {
322 ax = 0.0; bx = tsol; cx = 1.0;
323 }
89d8607f 324 FSR_DEBUG(" minimisation dans la direction");
7fd59977 325 math_BrentMinimum Sol(F, ax, bx, cx, tol1d, 100, tol1d);
326 if(Sol.IsDone()) {
327 if (Sol.Minimum() <= Result) {
3e42bd70
J
328 tsol = Sol.Location();
329 good = Standard_True;
89d8607f 330 FSR_DEBUG("t= "<<tsol<<" F ="<< Sol.Minimum() << " OldF = "<<Result)
7fd59977 331 }
332 }
333 }
334 if (good) {
335 // mise a jour du Delta
336 Dir.Multiply(tsol);
337 }
338 return good;
339}
340
341//------------------------------------------------------
342static void SearchDirection(const math_Matrix& DF,
89d8607f 343 const math_Vector& GH,
344 const math_Vector& FF,
345 Standard_Boolean ChangeDirection,
346 const math_Vector& InvLengthMax,
347 math_Vector& Direction,
348 Standard_Real& Dy)
7fd59977 349
350{
351 Standard_Integer Ninc = DF.ColNumber(), Neq = DF.RowNumber();
352 Standard_Real Eps = 1.e-32;
353 if (!ChangeDirection) {
354 if (Ninc == Neq) {
355 for (Standard_Integer i = FF.Lower(); i <= FF.Upper(); i++) {
89d8607f 356 Direction(i) = -FF(i);
7fd59977 357 }
358 math_Gauss Solut(DF, 1.e-9);
359 if (Solut.IsDone()) Solut.Solve(Direction);
360 else { // we have to "forget" singular directions.
89d8607f 361 FSR_DEBUG(" Matrice singuliere : On prend SVD");
3e42bd70 362 math_SVD SolvebySVD(DF);
7fd59977 363 if (SolvebySVD.IsDone()) SolvebySVD.Solve(-1*FF, Direction);
3e42bd70
J
364 else ChangeDirection = Standard_True;
365 }
7fd59977 366 }
367 else if (Ninc > Neq) {
368 math_SVD Solut(DF);
369 if (Solut.IsDone()) Solut.Solve(-1*FF, Direction);
370 else ChangeDirection = Standard_True;
371 }
372 else if (Ninc < Neq) { // Calcul par GaussLeastSquare
373 math_GaussLeastSquare Solut(DF);
374 if (Solut.IsDone()) Solut.Solve(-1*FF, Direction);
375 else ChangeDirection = Standard_True;
376 }
377 }
378 // Il vaut mieux interdire des directions trops longue
379 // Afin de blinder les cas trop mal conditionne
380 // PMN 12/05/97 Traitement des singularite dans les conges
381 // Sur des surfaces periodiques
89d8607f 382
7fd59977 383 Standard_Real ratio = Abs( Direction(Direction.Lower())
89d8607f 384 *InvLengthMax(Direction.Lower()) );
7fd59977 385 Standard_Integer i;
386 for (i = Direction.Lower()+1; i<=Direction.Upper(); i++) {
387 ratio = Max(ratio, Abs( Direction(i)*InvLengthMax(i)) );
388 }
389 if (ratio > 1) {
390 Direction /= ratio;
391 }
89d8607f 392
7fd59977 393 Dy = Direction*GH;
394 if (Dy >= -Eps) { // newton "ne descend pas" on prend le gradient
395 ChangeDirection = Standard_True;
396 }
397 if (ChangeDirection) { // On va faire un gradient !
398 for (i = Direction.Lower(); i <= Direction.Upper(); i++) {
399 Direction(i) = - GH(i);
400 }
401 Dy = - (GH.Norm2());
402 }
403}
404
405
406//=====================================================================
407static void SearchDirection(const math_Matrix& DF,
89d8607f 408 const math_Vector& GH,
409 const math_Vector& FF,
410 const math_IntegerVector& Constraints,
411 // const math_Vector& X, // Le point d'init
412 const math_Vector& , // Le point d'init
413 Standard_Boolean ChangeDirection,
7fd59977 414 const math_Vector& InvLengthMax,
89d8607f 415 math_Vector& Direction,
416 Standard_Real& Dy)
417 //Purpose : Recherche une direction (et un pas si Newton Fonctionne) le long
418 // d'une frontiere
419 //=====================================================================
7fd59977 420{
421 Standard_Integer Ninc = DF.ColNumber(), Neq = DF.RowNumber();
422 Standard_Integer i, j, k, Cons = 0;
423
424 // verification sur les bornes imposees:
425
426 for (i = 1; i <= Ninc; i++) {
427 if (Constraints(i) != 0) Cons++;
428 // sinon le systeme a resoudre ne change pas.
429 }
430
431 if (Cons == 0) {
432 SearchDirection(DF, GH, FF, ChangeDirection, InvLengthMax,
89d8607f 433 Direction, Dy);
7fd59977 434 }
435 else if (Cons == Ninc) { // il n'y a plus rien a faire...
436 for(Standard_Integer i = Direction.Lower(); i <= Direction.Upper(); i++) {
89d8607f 437 Direction(i) = 0;
438 }
7fd59977 439 Dy = 0;
440 }
441 else { //(1) Cas general : On definit un sous probleme
442 math_Matrix DF2(1, Neq, 1, Ninc-Cons);
443 math_Vector MyGH(1, Ninc-Cons);
444 math_Vector MyDirection(1, Ninc-Cons);
445 math_Vector MyInvLengthMax(1, Ninc);
446
447 for (k=1, i = 1; i <= Ninc; i++) {
448 if (Constraints(i) == 0) {
89d8607f 449 MyGH(k) = GH(i);
450 MyInvLengthMax(k) = InvLengthMax(i);
451 MyDirection(k) = Direction(i);
452 for (j = 1; j <= Neq; j++) {
453 DF2(j, k) = DF(j, i);
454 }
455 k++; //on passe a l'inconnue suivante
456 }
7fd59977 457 }
458 //(2) On le resoud
459 SearchDirection(DF2, MyGH, FF, ChangeDirection, MyInvLengthMax,
89d8607f 460 MyDirection, Dy);
7fd59977 461
462 // (3) On l'interprete...
463 // Reconstruction de Direction:
464 for (i = 1, k = 1; i <= Ninc; i++) {
465 if (Constraints(i) == 0) {
89d8607f 466 if (!ChangeDirection) {
467 Direction(i) = MyDirection(k);
468 }
469 else Direction(i) = - GH(i);
470 k++;
7fd59977 471 }
472 else {
89d8607f 473 Direction(i) = 0.0;
7fd59977 474 }
475 }
476 }
477}
478
479
480
481//====================================================
3e42bd70
J
482Standard_Boolean Bounds(const math_Vector& InfBound,
483 const math_Vector& SupBound,
484 const math_Vector& Tol,
485 math_Vector& Sol,
486 const math_Vector& SolSave,
487 math_IntegerVector& Constraints,
488 math_Vector& Delta,
489 Standard_Boolean& theIsNewSol)
89d8607f 490 //
491 // Purpose: Trims an initial solution Sol to be within a domain defined by
492 // InfBound and SupBound. Delta will contain a distance between final Sol and
493 // SolSave.
494 // IsNewSol returns False, if final Sol fully coincides with SolSave, i.e.
495 // if SolSave already lied on a boundary and initial Sol was fully beyond it
496 //======================================================
7fd59977 497{
498 Standard_Boolean Out = Standard_False;
499 Standard_Integer i, Ninc = Sol.Length();
500 Standard_Real monratio = 1;
89d8607f 501
3e42bd70
J
502 theIsNewSol = Standard_True;
503
7fd59977 504 // Calcul du ratio de recadrage
505 for (i = 1; i <= Ninc; i++) {
506 Constraints(i) = 0;
507 Delta(i) = Sol(i) - SolSave(i);
508 if (InfBound(i) == SupBound(i)) {
509 Constraints(i) = 1;
510 Out = Standard_True; // Ok mais, cela devrait etre eviter
511 }
512 else if(Sol(i) < InfBound(i)) {
513 Constraints(i) = 1;
514 Out = Standard_True;
3e42bd70
J
515 // Delta(i) is negative
516 if (-Delta(i) > Tol(i)) // Afin d'eviter des ratio nulles pour rien
517 monratio = Min(monratio, (InfBound(i) - SolSave(i))/Delta(i) );
7fd59977 518 }
519 else if (Sol(i) > SupBound(i)) {
520 Constraints(i) = 1;
521 Out = Standard_True;
3e42bd70
J
522 // Delta(i) is positive
523 if (Delta(i) > Tol(i))
524 monratio = Min(monratio, (SupBound(i) - SolSave(i))/Delta(i) );
7fd59977 525 }
526 }
527
528 if (Out){ // Troncature et derniers recadrage pour blinder (pb numeriques)
3e42bd70
J
529 if (monratio == 0.0) {
530 theIsNewSol = Standard_False;
531 Sol = SolSave;
532 Delta.Init (0.0);
533 } else {
534 Delta *= monratio;
535 Sol = SolSave+Delta;
536 for (i = 1; i <= Ninc; i++) {
537 if(Sol(i) < InfBound(i)) {
538 Sol(i) = InfBound(i);
539 Delta(i) = Sol(i) - SolSave(i);
540 }
541 else if (Sol(i) > SupBound(i)) {
542 Sol(i) = SupBound(i);
543 Delta(i) = Sol(i) - SolSave(i);
544 }
7fd59977 545 }
546 }
547 }
548 return Out;
549}
550
551
552
553
554
555math_FunctionSetRoot::math_FunctionSetRoot(math_FunctionSetWithDerivatives& F,
89d8607f 556 const math_Vector& Tolerance,
557 const Standard_Integer NbIterations) :
558Delta(1, F.NbVariables()),
559Sol(1, F.NbVariables()),
560DF(1, F.NbEquations(),
561 1, F.NbVariables()),
562 Tol(1,F.NbVariables()),
563
564 InfBound(1, F.NbVariables()),
565 SupBound(1, F.NbVariables()),
566
567 SolSave(1, F.NbVariables()),
568 GH(1, F.NbVariables()),
569 DH(1, F.NbVariables()),
570 DHSave(1, F.NbVariables()),
571 FF(1, F.NbEquations()),
572 PreviousSolution(1, F.NbVariables()),
573 Save(0, NbIterations),
574 Constraints(1, F.NbVariables()),
575 Temp1(1, F.NbVariables()),
576 Temp2(1, F.NbVariables()),
577 Temp3(1, F.NbVariables()),
578 Temp4(1, F.NbEquations())
7fd59977 579
580{
581 for (Standard_Integer i = 1; i <= Tol.Length(); i++) {
582 Tol(i) =Tolerance(i);
583 }
584 Itermax = NbIterations;
585}
586
587math_FunctionSetRoot::math_FunctionSetRoot(math_FunctionSetWithDerivatives& F,
89d8607f 588 const Standard_Integer NbIterations) :
589Delta(1, F.NbVariables()),
590Sol(1, F.NbVariables()),
591DF(1, F.NbEquations(),
592 1, F.NbVariables()),
593 Tol(1, F.NbVariables()),
594
595 InfBound(1, F.NbVariables()),
596 SupBound(1, F.NbVariables()),
597
598 SolSave(1, F.NbVariables()),
599 GH(1, F.NbVariables()),
600 DH(1, F.NbVariables()),
601 DHSave(1, F.NbVariables()),
602 FF(1, F.NbEquations()),
603 PreviousSolution(1, F.NbVariables()),
604 Save(0, NbIterations),
605 Constraints(1, F.NbVariables()),
606 Temp1(1, F.NbVariables()),
607 Temp2(1, F.NbVariables()),
608 Temp3(1, F.NbVariables()),
609 Temp4(1, F.NbEquations())
7fd59977 610
611{
612 Itermax = NbIterations;
613}
614
615
616
617math_FunctionSetRoot::math_FunctionSetRoot(math_FunctionSetWithDerivatives& F,
89d8607f 618 const math_Vector& StartingPoint,
619 const math_Vector& Tolerance,
620 const math_Vector& infBound,
621 const math_Vector& supBound,
622 const Standard_Integer NbIterations,
623 Standard_Boolean theStopOnDivergent) :
624Delta(1, F.NbVariables()),
625Sol(1, F.NbVariables()),
626DF(1, F.NbEquations(),
627 1, F.NbVariables()),
628 Tol(1,F.NbVariables()),
629
630
631 InfBound(1, F.NbVariables()),
632 SupBound(1, F.NbVariables()),
633
634 SolSave(1, F.NbVariables()),
635 GH(1, F.NbVariables()),
636 DH(1, F.NbVariables()),
637 DHSave(1, F.NbVariables()),
638 FF(1, F.NbEquations()),
639 PreviousSolution(1, F.NbVariables()),
640 Save(0, NbIterations),
641 Constraints(1, F.NbVariables()),
642 Temp1(1, F.NbVariables()),
643 Temp2(1, F.NbVariables()),
644 Temp3(1, F.NbVariables()),
645 Temp4(1, F.NbEquations())
7fd59977 646
647{
89d8607f 648
7fd59977 649 for (Standard_Integer i = 1; i <= Tol.Length(); i++) {
650 Tol(i) =Tolerance(i);
651 }
652 Itermax = NbIterations;
b659a6dc 653 Perform(F, StartingPoint, infBound, supBound, theStopOnDivergent);
7fd59977 654}
655
656math_FunctionSetRoot::math_FunctionSetRoot(math_FunctionSetWithDerivatives& F,
89d8607f 657 const math_Vector& StartingPoint,
658 const math_Vector& Tolerance,
659 const Standard_Integer NbIterations) :
660Delta(1, F.NbVariables()),
661Sol(1, F.NbVariables()),
662DF(1, F.NbEquations(),
663 1, StartingPoint.Length()),
664 Tol(1,F.NbVariables()),
665
666 InfBound(1, F.NbVariables()),
667 SupBound(1, F.NbVariables()),
668
669 SolSave(1, F.NbVariables()),
670 GH(1, F.NbVariables()),
671 DH(1, F.NbVariables()),
672 DHSave(1, F.NbVariables()),
673 FF(1, F.NbEquations()),
674 PreviousSolution(1, F.NbVariables()),
675 Save(0, NbIterations),
676 Constraints(1, F.NbVariables()),
677 Temp1(1, F.NbVariables()),
678 Temp2(1, F.NbVariables()),
679 Temp3(1, F.NbVariables()),
680 Temp4(1, F.NbEquations())
681
682{
7fd59977 683 for (Standard_Integer i = 1; i <= Tol.Length(); i++) {
684 Tol(i) = Tolerance(i);
685 }
686 Itermax = NbIterations;
687 InfBound.Init(RealFirst());
688 SupBound.Init(RealLast());
689 Perform(F, StartingPoint, InfBound, SupBound);
690}
691
6da30ff1 692math_FunctionSetRoot::~math_FunctionSetRoot()
693{
694}
7fd59977 695
696void math_FunctionSetRoot::SetTolerance(const math_Vector& Tolerance)
697{
698 for (Standard_Integer i = 1; i <= Tol.Length(); i++) {
699 Tol(i) = Tolerance(i);
700 }
701}
702
703void math_FunctionSetRoot::Perform(math_FunctionSetWithDerivatives& F,
89d8607f 704 const math_Vector& StartingPoint,
75259fc5 705 const math_Vector& theInfBound,
706 const math_Vector& theSupBound,
89d8607f 707 Standard_Boolean theStopOnDivergent)
7fd59977 708{
7fd59977 709 Standard_Integer Ninc = F.NbVariables(), Neq = F.NbEquations();
89d8607f 710
7fd59977 711 if ((Neq <= 0) ||
89d8607f 712 (StartingPoint.Length()!= Ninc) ||
75259fc5 713 (theInfBound.Length() != Ninc) ||
714 (theSupBound.Length() != Ninc)) { Standard_DimensionError:: Raise(); }
7fd59977 715
716 Standard_Integer i;
3e42bd70 717 Standard_Boolean ChangeDirection = Standard_False, Sort = Standard_False, isNewSol = Standard_False;
7fd59977 718 Standard_Boolean Good, Verif;
719 Standard_Boolean Stop;
3e42bd70 720 const Standard_Real EpsSqrt = 1.e-16, Eps = 1.e-32, Eps2 = 1.e-64, Progres = 0.005;
7fd59977 721 Standard_Real F2, PreviousMinimum, Dy, OldF;
722 Standard_Real Ambda, Ambda2, Gnr1, Oldgr;
723 math_Vector InvLengthMax(1, Ninc); // Pour bloquer les pas a 1/4 du domaine
75259fc5 724 math_IntegerVector aConstraints(1, Ninc); // Pour savoir sur quels bord on se trouve
7fd59977 725 for (i = 1; i <= Ninc ; i++) {
89d8607f 726 // modified by NIZHNY-MKK Mon Oct 3 18:03:50 2005
727 // InvLengthMax(i) = 1. / Max(Abs(SupBound(i) - InfBound(i))/4, 1.e-9);
75259fc5 728 InvLengthMax(i) = 1. / Max((theSupBound(i) - theInfBound(i))/4, 1.e-9);
89d8607f 729 }
7fd59977 730
731 MyDirFunction F_Dir(Temp1, Temp2, Temp3, Temp4, F);
732 Standard_Integer DescenteIter;
733
734 Done = Standard_False;
735 Sol = StartingPoint;
736 Kount = 0;
737
b659a6dc 738 //
739 myIsDivergent = Standard_False;
740 for (i = 1; i <= Ninc; i++)
741 {
75259fc5 742 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
b659a6dc 743 }
744 if (theStopOnDivergent & myIsDivergent)
745 {
746 return;
747 }
7fd59977 748 // Verification de la validite des inconnues par rapport aux bornes.
749 // Recentrage sur les bornes si pas valide.
750 for ( i = 1; i <= Ninc; i++) {
75259fc5 751 if (Sol(i) <= theInfBound(i)) Sol(i) = theInfBound(i);
752 else if (Sol(i) > theSupBound(i)) Sol(i) = theSupBound(i);
7fd59977 753 }
754
755 // Calcul de la premiere valeur de F et de son gradient
756 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
757 Done = Standard_False;
b659a6dc 758 if (!theStopOnDivergent || !myIsDivergent)
759 {
760 State = F.GetStateNumber();
761 }
7fd59977 762 return;
763 }
764 Ambda2 = Gnr1;
765 // Le rang 0 de Save ne doit servir q'au test accelarteur en fin de boucle
766 // s'il on est dejas sur la solution, il faut leurer ce test pour eviter
767 // de faire une seconde iteration...
3e42bd70 768 Save(0) = Max (F2, EpsSqrt);
5368adff 769 Standard_Real aTol_Func = Epsilon(F2);
89d8607f 770 FSR_DEBUG("=== Mode Debug de Function Set Root" << endl);
771 FSR_DEBUG(" F2 Initial = " << F2);
7fd59977 772
3e42bd70 773 if ((F2 <= Eps) || (Gnr1 <= Eps2)) {
b659a6dc 774 Done = Standard_False;
775 if (!theStopOnDivergent || !myIsDivergent)
776 {
777 Done = Standard_True;
778 State = F.GetStateNumber();
779 }
7fd59977 780 return;
781 }
782
783 for (Kount = 1; Kount <= Itermax; Kount++) {
784 PreviousMinimum = F2;
785 Oldgr = Gnr1;
786 PreviousSolution = Sol;
787 SolSave = Sol;
788
789 SearchDirection(DF, GH, FF, ChangeDirection, InvLengthMax, DH, Dy);
790 if (Abs(Dy) <= Eps) {
b659a6dc 791 Done = Standard_False;
792 if (!theStopOnDivergent || !myIsDivergent)
793 {
794 Done = Standard_True;
795 ////modified by jgv, 31.08.2011////
796 F.Value(Sol, FF); //update F before GetStateNumber
797 ///////////////////////////////////
798 State = F.GetStateNumber();
799 }
7fd59977 800 return;
801 }
802 if (ChangeDirection) {
3e42bd70 803 Ambda = Ambda2 / Sqrt(Abs(Dy));
7fd59977 804 if (Ambda > 1.0) Ambda = 1.0;
805 }
806 else {
807 Ambda = 1.0;
808 Ambda2 = 0.5*Ambda/DH.Norm();
809 }
810
811 for( i = Sol.Lower(); i <= Sol.Upper(); i++) {
812 Sol(i) = Sol(i) + Ambda * DH(i);
813 }
b659a6dc 814 //
815 for (i = 1; i <= Ninc; i++)
816 {
75259fc5 817 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
b659a6dc 818 }
819 if (theStopOnDivergent & myIsDivergent)
820 {
821 return;
822 }
823 //
75259fc5 824 Sort = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
825 aConstraints, Delta, isNewSol);
89d8607f 826
7fd59977 827
7fd59977 828 DHSave = GH;
3e42bd70 829 if (isNewSol) {
89d8607f 830 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
3e42bd70
J
831 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
832 Done = Standard_False;
b659a6dc 833 if (!theStopOnDivergent || !myIsDivergent)
834 {
835 State = F.GetStateNumber();
836 }
3e42bd70
J
837 return;
838 }
7fd59977 839 }
89d8607f 840
841 FSR_DEBUG("Kount = " << Kount);
842 FSR_DEBUG("Le premier F2 = " << F2);
843 FSR_DEBUG("Direction = " << ChangeDirection);
7fd59977 844
3e42bd70 845 if ((F2 <= Eps) || (Gnr1 <= Eps2)) {
b659a6dc 846 Done = Standard_False;
847 if (!theStopOnDivergent || !myIsDivergent)
848 {
849 Done = Standard_True;
850 ////modified by jgv, 31.08.2011////
851 F.Value(Sol, FF); //update F before GetStateNumber
852 ///////////////////////////////////
853 State = F.GetStateNumber();
854 }
7fd59977 855 return;
856 }
857
858 if (Sort || (F2/PreviousMinimum > Progres)) {
859 Dy = GH*DH;
860 OldF = PreviousMinimum;
861 Stop = Standard_False;
862 Good = Standard_False;
863 DescenteIter = 0;
864 Standard_Boolean Sortbis;
865
866 // -------------------------------------------------
867 // Traitement standard sans traitement des bords
868 // -------------------------------------------------
869 if (!Sort) { // si l'on est pas sortie on essaye de progresser en avant
89d8607f 870 while((F2/PreviousMinimum > Progres) && !Stop) {
871 if (F2 < OldF && (Dy < 0.0)) {
872 // On essaye de progresser dans cette direction.
873 FSR_DEBUG(" iteration de descente = " << DescenteIter);
874 DescenteIter++;
875 SolSave = Sol;
876 OldF = F2;
877 for( i = Sol.Lower(); i <= Sol.Upper(); i++) {
878 Sol(i) = Sol(i) + Ambda * DH(i);
879 }
880 //
881 for (i = 1; i <= Ninc; i++)
882 {
75259fc5 883 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
89d8607f 884 }
885 if (theStopOnDivergent & myIsDivergent)
886 {
887 return;
888 }
889 //
75259fc5 890 Stop = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
891 aConstraints, Delta, isNewSol);
89d8607f 892 FSR_DEBUG(" Augmentation de lambda");
893 Ambda *= 1.7;
b659a6dc 894 }
89d8607f 895 else {
896 if ((F2 >= OldF)||(F2 >= PreviousMinimum)) {
897 Good = Standard_False;
898 if (DescenteIter == 0) {
899 // C'est le premier pas qui flanche, on fait une interpolation.
900 // et on minimise si necessaire.
901 DescenteIter++;
902 Good = MinimizeDirection(SolSave, Delta, OldF, F2, DHSave, GH,
903 Tol, F_Dir);
904 }
905 else if (ChangeDirection || (DescenteIter>1)
906 || (OldF>PreviousMinimum) ) {
907 // La progression a ete utile, on minimise...
908 DescenteIter++;
909 Good = MinimizeDirection(PreviousSolution, SolSave, Sol,
910 OldF, Delta, Tol, F_Dir);
911 }
912 if (!Good) {
913 Sol = SolSave;
914 F2 = OldF;
915 }
916 else {
917 Sol = SolSave+Delta;
918 //
919 for (i = 1; i <= Ninc; i++)
920 {
75259fc5 921 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
89d8607f 922 }
923 if (theStopOnDivergent & myIsDivergent)
924 {
925 return;
926 }
927 //
75259fc5 928 Sort = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
929 aConstraints, Delta, isNewSol);
89d8607f 930 }
931 Sort = Standard_False; // On a rejete le point sur la frontiere
932 }
933 Stop = Standard_True; // et on sort dans tous les cas...
b659a6dc 934 }
89d8607f 935 DHSave = GH;
3e42bd70 936 if (isNewSol) {
89d8607f 937 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
3e42bd70
J
938 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
939 Done = Standard_False;
b659a6dc 940 if (!theStopOnDivergent || !myIsDivergent)
941 {
942 State = F.GetStateNumber();
943 }
3e42bd70
J
944 return;
945 }
946 }
89d8607f 947 Dy = GH*DH;
948 if (Abs(Dy) <= Eps) {
949 if (F2 > OldF)
3e42bd70 950 Sol = SolSave;
89d8607f 951 Done = Standard_False;
952 if (!theStopOnDivergent || !myIsDivergent)
953 {
954 Done = Standard_True;
b659a6dc 955 ////modified by jgv, 31.08.2011////
956 F.Value(Sol, FF); //update F before GetStateNumber
957 ///////////////////////////////////
89d8607f 958 State = F.GetStateNumber();
959 }
960 return;
961 }
962 if (DescenteIter >= 100) {
963 Stop = Standard_True;
964 }
965 }
966 FSR_DEBUG("--- Sortie du Traitement Standard");
967 FSR_DEBUG(" DescenteIter = "<<DescenteIter << " F2 = " << F2);
7fd59977 968 }
969 // ------------------------------------
970 // on passe au traitement des bords
971 // ------------------------------------
972 if (Sort) {
89d8607f 973 Stop = (F2 > 1.001*OldF); // Pour ne pas progresser sur le bord
974 Sortbis = Sort;
975 DescenteIter = 0;
976 while (Sortbis && ((F2<OldF)|| (DescenteIter == 0))
977 && (!Stop)) {
978 DescenteIter++;
979 // On essaye de progresser sur le bord
980 SolSave = Sol;
981 OldF = F2;
75259fc5 982 SearchDirection(DF, GH, FF, aConstraints, Sol,
89d8607f 983 ChangeDirection, InvLengthMax, DH, Dy);
984 FSR_DEBUG(" Conditional Direction = " << ChangeDirection);
985 if (Dy<-Eps) { //Pour eviter des calculs inutiles et des /0...
986 if (ChangeDirection) {
987
988 // Ambda = Ambda2 / Sqrt(Abs(Dy));
989 Ambda = Ambda2 / Sqrt(-Dy);
990 if (Ambda > 1.0) Ambda = 1.0;
991 }
992 else {
993 Ambda = 1.0;
994 Ambda2 = 0.5*Ambda/DH.Norm();
995 }
996
997 for( i = Sol.Lower(); i <= Sol.Upper(); i++) {
998 Sol(i) = Sol(i) + Ambda * DH(i);
999 }
1000 //
1001 for (i = 1; i <= Ninc; i++)
1002 {
75259fc5 1003 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
89d8607f 1004 }
1005 if (theStopOnDivergent & myIsDivergent)
1006 {
3e42bd70
J
1007 return;
1008 }
89d8607f 1009 //
75259fc5 1010 Sortbis = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
1011 aConstraints, Delta, isNewSol);
89d8607f 1012
1013 DHSave = GH;
1014 if (isNewSol) {
1015 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
1016 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
1017 Done = Standard_False;
1018 if (!theStopOnDivergent || !myIsDivergent)
1019 {
1020 State = F.GetStateNumber();
1021 }
1022 return;
b659a6dc 1023 }
3e42bd70 1024 }
89d8607f 1025 Ambda2 = Gnr1;
1026 FSR_DEBUG("--- Iteration au bords : " << DescenteIter);
1027 FSR_DEBUG("--- F2 = " << F2);
3e42bd70 1028 }
89d8607f 1029 else {
1030 Stop = Standard_True;
1031 }
1032
1033 while((F2/PreviousMinimum > Progres) && (F2<OldF) && (!Stop) ) {
1034 DescenteIter++;
1035 FSR_DEBUG("--- Iteration de descente conditionnel = " << DescenteIter);
1036 if (F2 < OldF && Dy < 0.0) {
1037 // On essaye de progresser dans cette direction.
1038 SolSave = Sol;
1039 OldF = F2;
1040 for( i = Sol.Lower(); i <= Sol.Upper(); i++) {
1041 Sol(i) = Sol(i) + Ambda * DH(i);
1042 }
1043 //
1044 for (i = 1; i <= Ninc; i++)
b659a6dc 1045 {
75259fc5 1046 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
b659a6dc 1047 }
89d8607f 1048 if (theStopOnDivergent & myIsDivergent)
1049 {
1050 return;
1051 }
1052 //
75259fc5 1053 Sortbis = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
1054 aConstraints, Delta, isNewSol);
89d8607f 1055 }
1056 DHSave = GH;
1057 if (isNewSol) {
1058 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
1059 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
1060 Done = Standard_False;
1061 if (!theStopOnDivergent || !myIsDivergent)
1062 {
1063 State = F.GetStateNumber();
1064 }
1065 return;
1066 }
1067 }
1068 Ambda2 = Gnr1;
1069 Dy = GH*DH;
1070 Stop = ((Dy >=0) || (DescenteIter >= 10) || Sortbis);
1071 }
1072 Stop = ((Dy >=0) || (DescenteIter >= 10));
1073 }
1074 if (((F2/PreviousMinimum > Progres) &&
1075 (F2>=OldF))||(F2>=PreviousMinimum)) {
1076 // On minimise par Brent
1077 DescenteIter++;
1078 Good = MinimizeDirection(SolSave, Delta, OldF, F2,
1079 DHSave, GH, Tol, F_Dir);
1080 if (!Good) {
1081 Sol = SolSave;
1082 Sort = Standard_False;
1083 }
1084 else {
1085 Sol = SolSave + Delta;
1086 //
1087 for (i = 1; i <= Ninc; i++)
1088 {
75259fc5 1089 myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i));
89d8607f 1090 }
1091 if (theStopOnDivergent & myIsDivergent)
1092 {
3e42bd70
J
1093 return;
1094 }
89d8607f 1095 //
75259fc5 1096 Sort = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave,
1097 aConstraints, Delta, isNewSol);
89d8607f 1098 if (isNewSol) {
1099 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
1100 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
1101 Done = Standard_False;
1102 if (!theStopOnDivergent || !myIsDivergent)
1103 {
1104 State = F.GetStateNumber();
1105 }
1106 return;
1107 }
1108 }
1109 }
1110 Dy = GH*DH;
1111 }
1112 FSR_DEBUG("--- Sortie du Traitement des Bords");
1113 FSR_DEBUG("--- DescenteIter = "<<DescenteIter << " F2 = " << F2);
7fd59977 1114 }
1115 }
1116
1117 // ---------------------------------------------
1118 // on passe aux tests d'ARRET
1119 // ---------------------------------------------
1120 Save(Kount) = F2;
1121 // Est ce la solution ?
1122 if (ChangeDirection) Verif = Standard_True;
89d8607f 1123 // Gradient : Il faut eviter de boucler
7fd59977 1124 else {
1125 Verif = Standard_False;
1126 if (Kount > 1) { // Pour accelerer les cas quasi-quadratique
89d8607f 1127 if (Save(Kount-1)<1.e-4*Save(Kount-2)) Verif = Standard_True;
7fd59977 1128 }
1129 else Verif = (F2 < 1.e-6*Save(0)); //Pour les cas dejas solutions
1130 }
1131 if (Verif) {
1132 for(i = Delta.Lower(); i <= Delta.Upper(); i++) {
89d8607f 1133 Delta(i) = PreviousSolution(i) - Sol(i);
7fd59977 1134 }
89d8607f 1135
7fd59977 1136 if (IsSolutionReached(F)) {
89d8607f 1137 if (PreviousMinimum < F2) {
1138 Sol = SolSave;
1139 }
1140 Done = Standard_False;
1141 if (!theStopOnDivergent || !myIsDivergent)
1142 {
1143 Done = Standard_True;
b659a6dc 1144 ////modified by jgv, 31.08.2011////
1145 F.Value(Sol, FF); //update F before GetStateNumber
1146 ///////////////////////////////////
89d8607f 1147 State = F.GetStateNumber();
1148 }
1149 return;
7fd59977 1150 }
1151 }
1152 //fin du test solution
89d8607f 1153
7fd59977 1154 // Analyse de la progression...
5368adff 1155 //comparison of current minimum and previous minimum
1156 if ((F2 - PreviousMinimum) <= aTol_Func){
7fd59977 1157 if (Kount > 5) {
89d8607f 1158 // L'historique est il bon ?
1159 if (F2 >= 0.95*Save(Kount - 5)) {
1160 if (!ChangeDirection) ChangeDirection = Standard_True;
1161 else
1162 {
1163 Done = Standard_False;
1164 if (!theStopOnDivergent || !myIsDivergent)
1165 {
1166 Done = Standard_True;
1167 State = F.GetStateNumber();
1168 }
1169 return; // si un gain inf a 5% on sort
1170 }
1171 }
1172 else ChangeDirection = Standard_False; //Si oui on recommence
7fd59977 1173 }
1174 else ChangeDirection = Standard_False; //Pas d'historique on continue
1175 // Si le gradient ne diminue pas suffisemment par newton on essaie
1176 // le gradient sauf si f diminue (aussi bizarre que cela puisse
1177 // paraitre avec NEWTON le gradient de f peut augmenter alors que f
1178 // diminue: dans ce cas il faut garder NEWTON)
1179 if ((Gnr1 > 0.9*Oldgr) &&
89d8607f 1180 (F2 > 0.5*PreviousMinimum)) {
1181 ChangeDirection = Standard_True;
7fd59977 1182 }
1183
1184 // Si l'on ne decide pas de changer de strategie, on verifie,
1185 // si ce n'est dejas fait
1186 if ((!ChangeDirection) && (!Verif)) {
89d8607f 1187 for(i = Delta.Lower(); i <= Delta.Upper(); i++) {
1188 Delta(i) = PreviousSolution(i) - Sol(i);
1189 }
1190 if (IsSolutionReached(F)) {
1191 Done = Standard_False;
1192 if (!theStopOnDivergent || !myIsDivergent)
1193 {
1194 Done = Standard_True;
b659a6dc 1195 ////modified by jgv, 31.08.2011////
1196 F.Value(Sol, FF); //update F before GetStateNumber
1197 ///////////////////////////////////
89d8607f 1198 State = F.GetStateNumber();
1199 }
1200 return;
1201 }
7fd59977 1202 }
1203 }
1204 else { // Cas de regression
1205 if (!ChangeDirection) { // On passe au gradient
89d8607f 1206 ChangeDirection = Standard_True;
1207 Sol = PreviousSolution;
1208 // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1);
1209 if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) {
1210 Done = Standard_False;
1211 if (!theStopOnDivergent || !myIsDivergent)
1212 {
1213 State = F.GetStateNumber();
1214 }
1215 return;
1216 }
7fd59977 1217 }
5368adff 1218 else
1219 {
89d8607f 1220
b659a6dc 1221 if (!theStopOnDivergent || !myIsDivergent)
1222 {
1223 State = F.GetStateNumber();
1224 }
5368adff 1225 return; // y a plus d'issues
1226 }
7fd59977 1227 }
1228 }
b659a6dc 1229 if (!theStopOnDivergent || !myIsDivergent)
1230 {
1231 State = F.GetStateNumber();
1232 }
7fd59977 1233}
1234
1235
1236
1237
1238Standard_Boolean math_FunctionSetRoot::IsSolutionReached(math_FunctionSetWithDerivatives& ) {
89d8607f 1239 for(Standard_Integer i = 1; i<= Sol.Length(); i++) {
1240 if(Abs(Delta(i)) > Tol(i)) {return Standard_False;}
1241 }
1242 return Standard_True;
7fd59977 1243}
1244
1245
1246void math_FunctionSetRoot::Dump(Standard_OStream& o) const {
89d8607f 1247 o<<" math_FunctionSetRoot";
1248 if (Done) {
1249 o << " Status = Done\n";
1250 o << " Location value = " << Sol << "\n";
1251 o << " Number of iterations = " << Kount << "\n";
1252 }
1253 else {
1254 o<<"Status = Not Done\n";
1255 }
7fd59977 1256}
1257
1258
1259void math_FunctionSetRoot::Root(math_Vector& Root) const{
1260 StdFail_NotDone_Raise_if(!Done, " ");
1261 Standard_DimensionError_Raise_if(Root.Length() != Sol.Length(), " ");
1262 Root = Sol;
1263}
1264
1265
1266void math_FunctionSetRoot::FunctionSetErrors(math_Vector& Err) const{
1267 StdFail_NotDone_Raise_if(!Done, " ");
1268 Standard_DimensionError_Raise_if(Err.Length() != Sol.Length(), " ");
1269 Err = Delta;
1270}