// Copyright (c) 1997-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // pmn 15/05/97 pas de Gauss avec des pivot trop petit. SVD fait mieux // l'affaire + limitation de la longeur du pas + qq comentaire issus d'EUCLID3 // pmn 10/06/97 refonte totale du traitement des bords + ajustement des init // et des tolerances pour brent... //#ifndef OCCT_DEBUG #define No_Standard_RangeError #define No_Standard_OutOfRange #define No_Standard_DimensionError //#endif //math_FunctionSetRoot.cxx #include #include #include #include #include #include #include #include #include #include #include #include //=========================================================================== // - A partir d une solution de depart, recherche d une direction.( Newton la // plupart du temps, gradient si Newton echoue. // - Recadrage au niveau des bornes avec recalcul de la direction si une // inconnue a une valeur imposee. // -Si On ne sort pas des bornes // Tant que (On ne progresse pas assez ou on ne change pas de direction) // . Si (Progression encore possible) // Si (On ne sort pas des bornes) // On essaye de progresser dans cette meme direction. // Sinon // On diminue le pas d'avancement ou on change de direction. // Sinon // Si on depasse le minimum // On fait une interpolation parabolique. // - Si on a progresse sur F // On fait les tests d'arret // Sinon // On change de direction //============================================================================ #define FSR_DEBUG(arg) // Uncomment the following code to have debug output to cout //========================================================== //static Standard_Boolean mydebug = Standard_True; //#undef FSR_DEBUG //#define FSR_DEBUG(arg) {if (mydebug) { std::cout << arg << std::endl; }} //=========================================================== class MyDirFunction : public math_Function { math_Vector *P0; math_Vector *Dir; math_Vector *P; math_Vector *FV; math_FunctionSetWithDerivatives *F; public : MyDirFunction(math_Vector& V1, math_Vector& V2, math_Vector& V3, math_Vector& V4, math_FunctionSetWithDerivatives& f) ; void Initialize(const math_Vector& p0, const math_Vector& dir) const; //For hp : Standard_Boolean Value(const math_Vector& Sol, math_Vector& FF, math_Matrix& DF, math_Vector& GH, Standard_Real& F2, Standard_Real& Gnr1); // Standard_Boolean MyDirFunction::Value(const math_Vector& Sol, math_Vector& FF, // math_Matrix& DF, math_Vector& GH, // Standard_Real& F2, Standard_Real& Gnr1); Standard_Boolean Value(const Standard_Real x, Standard_Real& fval) ; }; MyDirFunction::MyDirFunction(math_Vector& V1, math_Vector& V2, math_Vector& V3, math_Vector& V4, math_FunctionSetWithDerivatives& f) { P0 = &V1; Dir = &V2; P = &V3; FV = &V4; F = &f; } void MyDirFunction::Initialize(const math_Vector& p0, const math_Vector& dir) const { *P0 = p0; *Dir = dir; } Standard_Boolean MyDirFunction::Value(const Standard_Real x, Standard_Real& fval) { Standard_Real p; for(Standard_Integer i = P->Lower(); i <= P->Upper(); i++) { p = Dir->Value(i); P->Value(i) = p * x + P0->Value(i); } if( F->Value(*P, *FV) ) { Standard_Real aVal = 0.0; for(Standard_Integer i = FV->Lower(); i <= FV->Upper(); i++) { aVal = FV->Value(i); if(aVal <= -1.e+100) // Precision::HalfInfinite() later return Standard_False; else if(aVal >= 1.e+100) // Precision::HalfInfinite() later return Standard_False; } fval = 0.5 * (FV->Norm2()); return Standard_True; } return Standard_False; } Standard_Boolean MyDirFunction::Value(const math_Vector& Sol, math_Vector& FF, math_Matrix& DF, math_Vector& GH, Standard_Real& F2, Standard_Real& Gnr1) { if( F->Values(Sol, FF, DF) ) { Standard_Real aVal = 0.; for(Standard_Integer i = FF.Lower(); i <= FF.Upper(); i++) { // modified by NIZHNY-MKK Mon Oct 3 17:56:50 2005.BEGIN aVal = FF.Value(i); if(aVal < 0.) { if(aVal <= -1.e+100) // Precision::HalfInfinite() later // if(Precision::IsInfinite(Abs(FF.Value(i)))) { // F2 = Precision::Infinite(); // Gnr1 = Precision::Infinite(); return Standard_False; } else if(aVal >= 1.e+100) // Precision::HalfInfinite() later return Standard_False; // modified by NIZHNY-MKK Mon Oct 3 17:57:05 2005.END } F2 = 0.5 * (FF.Norm2()); GH.TMultiply(DF, FF); for(Standard_Integer i = GH.Lower(); i <= GH.Upper(); i++) { if(Precision::IsInfinite((GH.Value(i)))) { return Standard_False; } } Gnr1 = GH.Norm2(); return Standard_True; } return Standard_False; } //-------------------------------------------------------------- static Standard_Boolean MinimizeDirection(const math_Vector& P0, const math_Vector& P1, const math_Vector& P2, const Standard_Real F1, math_Vector& Delta, const math_Vector& Tol, MyDirFunction& F) // Purpose : minimisation a partir de 3 points //------------------------------------------------------- { // (1) Evaluation d'un tolerance parametrique 1D Standard_Real tol1d = 2.1 , invnorme, tsol; Standard_Real Eps = 1.e-16; Standard_Real ax, bx, cx; for (Standard_Integer ii =1; ii<=Tol.Length(); ii++) { invnorme = Abs(Delta(ii)); if (invnorme>Eps) tol1d = Min(tol1d, Tol(ii) / invnorme); } if (tol1d > 1.9) return Standard_False; //Pas la peine de se fatiguer tol1d /= 3; //JR/Hp : math_Vector PP0 = P0 ; math_Vector PP1 = P1 ; Delta = PP1 - PP0; // Delta = P1 - P0; invnorme = Delta.Norm(); if (invnorme <= Eps) return Standard_False; invnorme = ((Standard_Real) 1) / invnorme; F.Initialize(P1, Delta); // (2) On minimise FSR_DEBUG (" minimisation dans la direction") ax = -1; bx = 0; cx = (P2-P1).Norm()*invnorme; if (cx < 1.e-2) return Standard_False; math_BrentMinimum Sol(tol1d, 100, tol1d); Sol.Perform(F, ax, bx, cx); if(Sol.IsDone()) { tsol = Sol.Location(); if (Sol.Minimum() < F1) { Delta.Multiply(tsol); return Standard_True; } } return Standard_False; } //---------------------------------------------------------------------- static Standard_Boolean MinimizeDirection(const math_Vector& P, math_Vector& Dir, const Standard_Real& PValue, const Standard_Real& PDirValue, const math_Vector& Gradient, const math_Vector& DGradient, const math_Vector& Tol, MyDirFunction& F) // Purpose: minimisation a partir de 2 points et une derives //---------------------------------------------------------------------- { if(Precision::IsInfinite(PValue) || Precision::IsInfinite(PDirValue)) { return Standard_False; } // (0) Evaluation d'un tolerance parametrique 1D Standard_Boolean good = Standard_False; Standard_Real Eps = 1.e-20; Standard_Real tol1d = 1.1, Result = PValue, absdir; for (Standard_Integer ii =1; ii<=Tol.Length(); ii++) { absdir = Abs(Dir(ii)); if (absdir >Eps) tol1d = Min(tol1d, Tol(ii) / absdir); } if (tol1d > 0.9) return Standard_False; // (1) On realise une premiere interpolation quadratique Standard_Real ax, bx, cx, df1, df2, Delta, tsol, fsol, tsolbis; FSR_DEBUG(" essai d interpolation"); df1 = Gradient*Dir; df2 = DGradient*Dir; if (df1<-Eps && df2>Eps) { // cuvette tsol = - df1 / (df2 - df1); } else { cx = PValue; bx = df1; ax = PDirValue - (bx+cx); if (Abs(ax) <= Eps) { // cas lineaire if ((Abs(bx) >= Eps)) tsol = - cx/bx; else tsol = 0; } else { // cas quadratique Delta = bx*bx - 4*ax*cx; if (Delta > 1.e-9) { // il y a des racines, on prend la plus proche de 0 Delta = Sqrt(Delta); tsol = -(bx + Delta); tsolbis = (Delta - bx); if (Abs(tsolbis) < Abs(tsol)) tsol = tsolbis; tsol /= 2*ax; } else { // pas ou peu de racine : on "extremise" tsol = -(0.5*bx)/ax; } } } if (Abs(tsol) >= 1) return Standard_False; //resultat sans interet F.Initialize(P, Dir); F.Value(tsol, fsol); if (fsol // perform additional computations. if (Gradient.Norm2() > 1.0 / Precision::SquareConfusion() && tsol > ax && tsol < cx) // Solution inside of (ax, cx) interval. { // First and second part invocation. Sol.Perform(F, ax, (ax + tsol) / 2.0, tsol); if(Sol.IsDone()) { if (Sol.Minimum() <= Result) { tsol = Sol.Location(); good = Standard_True; Result = Sol.Minimum(); } } Sol.Perform(F, tsol, (cx + tsol) / 2.0, cx); if(Sol.IsDone()) { if (Sol.Minimum() <= Result) { tsol = Sol.Location(); good = Standard_True; Result = Sol.Minimum(); } } } } // if (Sol.Minimum() <= Result) } // if(Sol.IsDone()) } if (good) { // mise a jour du Delta Dir.Multiply(tsol); } return good; } //------------------------------------------------------ static void SearchDirection(const math_Matrix& DF, const math_Vector& GH, const math_Vector& FF, Standard_Boolean ChangeDirection, const math_Vector& InvLengthMax, math_Vector& Direction, Standard_Real& Dy) { Standard_Integer Ninc = DF.ColNumber(), Neq = DF.RowNumber(); Standard_Real Eps = 1.e-32; if (!ChangeDirection) { if (Ninc == Neq) { for (Standard_Integer i = FF.Lower(); i <= FF.Upper(); i++) { Direction(i) = -FF(i); } math_Gauss Solut(DF, 1.e-9); if (Solut.IsDone()) Solut.Solve(Direction); else { // we have to "forget" singular directions. FSR_DEBUG(" Matrice singuliere : On prend SVD"); math_SVD SolvebySVD(DF); if (SolvebySVD.IsDone()) SolvebySVD.Solve(-1*FF, Direction); else ChangeDirection = Standard_True; } } else if (Ninc > Neq) { math_SVD Solut(DF); if (Solut.IsDone()) Solut.Solve(-1*FF, Direction); else ChangeDirection = Standard_True; } else if (Ninc < Neq) { // Calcul par GaussLeastSquare math_GaussLeastSquare Solut(DF); if (Solut.IsDone()) Solut.Solve(-1*FF, Direction); else ChangeDirection = Standard_True; } } // Il vaut mieux interdire des directions trops longue // Afin de blinder les cas trop mal conditionne // PMN 12/05/97 Traitement des singularite dans les conges // Sur des surfaces periodiques Standard_Real ratio = Abs( Direction(Direction.Lower()) *InvLengthMax(Direction.Lower()) ); Standard_Integer i; for (i = Direction.Lower()+1; i<=Direction.Upper(); i++) { ratio = Max(ratio, Abs( Direction(i)*InvLengthMax(i)) ); } if (ratio > 1) { Direction /= ratio; } Dy = Direction*GH; if (Dy >= -Eps) { // newton "ne descend pas" on prend le gradient ChangeDirection = Standard_True; } if (ChangeDirection) { // On va faire un gradient ! for (i = Direction.Lower(); i <= Direction.Upper(); i++) { Direction(i) = - GH(i); } Dy = - (GH.Norm2()); } } //===================================================================== static void SearchDirection(const math_Matrix& DF, const math_Vector& GH, const math_Vector& FF, const math_IntegerVector& Constraints, // const math_Vector& X, // Le point d'init const math_Vector& , // Le point d'init Standard_Boolean ChangeDirection, const math_Vector& InvLengthMax, math_Vector& Direction, Standard_Real& Dy) //Purpose : Recherche une direction (et un pas si Newton Fonctionne) le long // d'une frontiere //===================================================================== { Standard_Integer Ninc = DF.ColNumber(), Neq = DF.RowNumber(); Standard_Integer i, j, k, Cons = 0; // verification sur les bornes imposees: for (i = 1; i <= Ninc; i++) { if (Constraints(i) != 0) Cons++; // sinon le systeme a resoudre ne change pas. } if (Cons == 0) { SearchDirection(DF, GH, FF, ChangeDirection, InvLengthMax, Direction, Dy); } else if (Cons == Ninc) { // il n'y a plus rien a faire... for(i = Direction.Lower(); i <= Direction.Upper(); i++) { Direction(i) = 0; } Dy = 0; } else { //(1) Cas general : On definit un sous probleme math_Matrix DF2(1, Neq, 1, Ninc-Cons); math_Vector MyGH(1, Ninc-Cons); math_Vector MyDirection(1, Ninc-Cons); math_Vector MyInvLengthMax(1, Ninc); for (k=1, i = 1; i <= Ninc; i++) { if (Constraints(i) == 0) { MyGH(k) = GH(i); MyInvLengthMax(k) = InvLengthMax(i); MyDirection(k) = Direction(i); for (j = 1; j <= Neq; j++) { DF2(j, k) = DF(j, i); } k++; //on passe a l'inconnue suivante } } //(2) On le resoud SearchDirection(DF2, MyGH, FF, ChangeDirection, MyInvLengthMax, MyDirection, Dy); // (3) On l'interprete... // Reconstruction de Direction: for (i = 1, k = 1; i <= Ninc; i++) { if (Constraints(i) == 0) { if (!ChangeDirection) { Direction(i) = MyDirection(k); } else Direction(i) = - GH(i); k++; } else { Direction(i) = 0.0; } } } } //==================================================== Standard_Boolean Bounds(const math_Vector& InfBound, const math_Vector& SupBound, const math_Vector& Tol, math_Vector& Sol, const math_Vector& SolSave, math_IntegerVector& Constraints, math_Vector& Delta, Standard_Boolean& theIsNewSol) // // Purpose: Trims an initial solution Sol to be within a domain defined by // InfBound and SupBound. Delta will contain a distance between final Sol and // SolSave. // IsNewSol returns False, if final Sol fully coincides with SolSave, i.e. // if SolSave already lied on a boundary and initial Sol was fully beyond it //====================================================== { Standard_Boolean Out = Standard_False; Standard_Integer i, Ninc = Sol.Length(); Standard_Real monratio = 1; theIsNewSol = Standard_True; // Calcul du ratio de recadrage for (i = 1; i <= Ninc; i++) { Constraints(i) = 0; Delta(i) = Sol(i) - SolSave(i); if (InfBound(i) == SupBound(i)) { Constraints(i) = 1; Out = Standard_True; // Ok mais, cela devrait etre eviter } else if(Sol(i) < InfBound(i)) { Constraints(i) = 1; Out = Standard_True; // Delta(i) is negative if (-Delta(i) > Tol(i)) // Afin d'eviter des ratio nulles pour rien monratio = Min(monratio, (InfBound(i) - SolSave(i))/Delta(i) ); } else if (Sol(i) > SupBound(i)) { Constraints(i) = 1; Out = Standard_True; // Delta(i) is positive if (Delta(i) > Tol(i)) monratio = Min(monratio, (SupBound(i) - SolSave(i))/Delta(i) ); } } if (Out){ // Troncature et derniers recadrage pour blinder (pb numeriques) if (monratio == 0.0) { theIsNewSol = Standard_False; Sol = SolSave; Delta.Init (0.0); } else { Delta *= monratio; Sol = SolSave+Delta; for (i = 1; i <= Ninc; i++) { if(Sol(i) < InfBound(i)) { Sol(i) = InfBound(i); Delta(i) = Sol(i) - SolSave(i); } else if (Sol(i) > SupBound(i)) { Sol(i) = SupBound(i); Delta(i) = Sol(i) - SolSave(i); } } } } return Out; } //======================================================================= //function : math_FunctionSetRoot //purpose : Constructor //======================================================================= math_FunctionSetRoot::math_FunctionSetRoot( math_FunctionSetWithDerivatives& theFunction, const math_Vector& theTolerance, const Standard_Integer theNbIterations) : Delta(1, theFunction.NbVariables()), Sol (1, theFunction.NbVariables()), DF (1, theFunction.NbEquations() , 1, theFunction.NbVariables()), Tol (1, theFunction.NbVariables()), Done (Standard_False), Kount (0), State (0), Itermax (theNbIterations), InfBound(1, theFunction.NbVariables(), RealFirst()), SupBound(1, theFunction.NbVariables(), RealLast ()), SolSave (1, theFunction.NbVariables()), GH (1, theFunction.NbVariables()), DH (1, theFunction.NbVariables()), DHSave (1, theFunction.NbVariables()), FF (1, theFunction.NbEquations()), PreviousSolution(1, theFunction.NbVariables()), Save (0, theNbIterations), Constraints(1, theFunction.NbVariables()), Temp1 (1, theFunction.NbVariables()), Temp2 (1, theFunction.NbVariables()), Temp3 (1, theFunction.NbVariables()), Temp4 (1, theFunction.NbEquations()), myIsDivergent(Standard_False) { SetTolerance(theTolerance); } //======================================================================= //function : math_FunctionSetRoot //purpose : Constructor //======================================================================= math_FunctionSetRoot::math_FunctionSetRoot(math_FunctionSetWithDerivatives& theFunction, const Standard_Integer theNbIterations) : Delta(1, theFunction.NbVariables()), Sol (1, theFunction.NbVariables()), DF (1, theFunction.NbEquations() , 1, theFunction.NbVariables()), Tol (1, theFunction.NbVariables()), Done (Standard_False), Kount (0), State (0), Itermax (theNbIterations), InfBound(1, theFunction.NbVariables(), RealFirst()), SupBound(1, theFunction.NbVariables(), RealLast ()), SolSave (1, theFunction.NbVariables()), GH (1, theFunction.NbVariables()), DH (1, theFunction.NbVariables()), DHSave (1, theFunction.NbVariables()), FF (1, theFunction.NbEquations()), PreviousSolution(1, theFunction.NbVariables()), Save (0, theNbIterations), Constraints(1, theFunction.NbVariables()), Temp1 (1, theFunction.NbVariables()), Temp2 (1, theFunction.NbVariables()), Temp3 (1, theFunction.NbVariables()), Temp4 (1, theFunction.NbEquations()), myIsDivergent(Standard_False) { } //======================================================================= //function : ~math_FunctionSetRoot //purpose : Destructor //======================================================================= math_FunctionSetRoot::~math_FunctionSetRoot() { } //======================================================================= //function : SetTolerance //purpose : //======================================================================= void math_FunctionSetRoot::SetTolerance(const math_Vector& theTolerance) { for (Standard_Integer i = 1; i <= Tol.Length(); ++i) Tol(i) = theTolerance(i); } //======================================================================= //function : Perform //purpose : //======================================================================= void math_FunctionSetRoot::Perform(math_FunctionSetWithDerivatives& theFunction, const math_Vector& theStartingPoint, const Standard_Boolean theStopOnDivergent) { Perform(theFunction, theStartingPoint, InfBound, SupBound, theStopOnDivergent); } //======================================================================= //function : Perform //purpose : //======================================================================= void math_FunctionSetRoot::Perform(math_FunctionSetWithDerivatives& F, const math_Vector& StartingPoint, const math_Vector& theInfBound, const math_Vector& theSupBound, Standard_Boolean theStopOnDivergent) { Standard_Integer Ninc = F.NbVariables(), Neq = F.NbEquations(); if ((Neq <= 0) || (StartingPoint.Length()!= Ninc) || (theInfBound.Length() != Ninc) || (theSupBound.Length() != Ninc)) { throw Standard_DimensionError(); } Standard_Integer i; Standard_Boolean ChangeDirection = Standard_False, Sort = Standard_False, isNewSol = Standard_False; Standard_Boolean Good, Verif; Standard_Boolean Stop; const Standard_Real EpsSqrt = 1.e-16, Eps = 1.e-32, Eps2 = 1.e-64, Progres = 0.005; Standard_Real F2, PreviousMinimum, Dy, OldF; Standard_Real Ambda, Ambda2, Gnr1, Oldgr; math_Vector InvLengthMax(1, Ninc); // Pour bloquer les pas a 1/4 du domaine math_IntegerVector aConstraints(1, Ninc); // Pour savoir sur quels bord on se trouve for (i = 1; i <= Ninc ; i++) { const Standard_Real aSupBound = Min (theSupBound(i), Precision::Infinite()); const Standard_Real anInfBound = Max (theInfBound(i), -Precision::Infinite()); InvLengthMax(i) = 1. / Max((aSupBound - anInfBound)/4, 1.e-9); } MyDirFunction F_Dir(Temp1, Temp2, Temp3, Temp4, F); Standard_Integer DescenteIter; Done = Standard_False; Sol = StartingPoint; Kount = 0; // myIsDivergent = Standard_False; for (i = 1; i <= Ninc; i++) { myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i)); } if (theStopOnDivergent & myIsDivergent) { return; } // Verification de la validite des inconnues par rapport aux bornes. // Recentrage sur les bornes si pas valide. for ( i = 1; i <= Ninc; i++) { if (Sol(i) <= theInfBound(i)) Sol(i) = theInfBound(i); else if (Sol(i) > theSupBound(i)) Sol(i) = theSupBound(i); } // Calcul de la premiere valeur de F et de son gradient if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { State = F.GetStateNumber(); } return; } Ambda2 = Gnr1; // Le rang 0 de Save ne doit servir q'au test accelarteur en fin de boucle // s'il on est dejas sur la solution, il faut leurer ce test pour eviter // de faire une seconde iteration... Save(0) = Max (F2, EpsSqrt); Standard_Real aTol_Func = Epsilon(F2); FSR_DEBUG("=== Mode Debug de Function Set Root" << std::endl); FSR_DEBUG(" F2 Initial = " << F2); if ((F2 <= Eps) || (Gnr1 <= Eps2)) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { Done = Standard_True; State = F.GetStateNumber(); } return; } for (Kount = 1; Kount <= Itermax; Kount++) { PreviousMinimum = F2; Oldgr = Gnr1; PreviousSolution = Sol; SolSave = Sol; SearchDirection(DF, GH, FF, ChangeDirection, InvLengthMax, DH, Dy); if (Abs(Dy) <= Eps) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { Done = Standard_True; ////modified by jgv, 31.08.2011//// F.Value(Sol, FF); //update F before GetStateNumber /////////////////////////////////// State = F.GetStateNumber(); } return; } if (ChangeDirection) { Ambda = Ambda2 / Sqrt(Abs(Dy)); if (Ambda > 1.0) Ambda = 1.0; } else { Ambda = 1.0; Ambda2 = 0.5*Ambda/DH.Norm(); } for( i = Sol.Lower(); i <= Sol.Upper(); i++) { Sol(i) = Sol(i) + Ambda * DH(i); } // for (i = 1; i <= Ninc; i++) { myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i)); } if (theStopOnDivergent & myIsDivergent) { return; } // Sort = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave, aConstraints, Delta, isNewSol); DHSave = GH; if (isNewSol) { // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1); if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { State = F.GetStateNumber(); } return; } } FSR_DEBUG("Kount = " << Kount); FSR_DEBUG("Le premier F2 = " << F2); FSR_DEBUG("Direction = " << ChangeDirection); if ((F2 <= Eps) || (Gnr1 <= Eps2)) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { Done = Standard_True; ////modified by jgv, 31.08.2011//// F.Value(Sol, FF); //update F before GetStateNumber /////////////////////////////////// State = F.GetStateNumber(); } return; } if (Sort || (F2/PreviousMinimum > Progres)) { Dy = GH*DH; OldF = PreviousMinimum; Stop = Standard_False; Good = Standard_False; DescenteIter = 0; Standard_Boolean Sortbis; // ------------------------------------------------- // Traitement standard sans traitement des bords // ------------------------------------------------- if (!Sort) { // si l'on est pas sortie on essaye de progresser en avant while((F2/PreviousMinimum > Progres) && !Stop) { if (F2 < OldF && (Dy < 0.0)) { // On essaye de progresser dans cette direction. FSR_DEBUG(" iteration de descente = " << DescenteIter); DescenteIter++; SolSave = Sol; OldF = F2; for( i = Sol.Lower(); i <= Sol.Upper(); i++) { Sol(i) = Sol(i) + Ambda * DH(i); } // for (i = 1; i <= Ninc; i++) { myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i)); } if (theStopOnDivergent & myIsDivergent) { return; } // Stop = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave, aConstraints, Delta, isNewSol); FSR_DEBUG(" Augmentation de lambda"); Ambda *= 1.7; } else { if ((F2 >= OldF)||(F2 >= PreviousMinimum)) { Good = Standard_False; if (DescenteIter == 0) { // C'est le premier pas qui flanche, on fait une interpolation. // et on minimise si necessaire. DescenteIter++; Good = MinimizeDirection(SolSave, Delta, OldF, F2, DHSave, GH, Tol, F_Dir); } else if (ChangeDirection || (DescenteIter>1) || (OldF>PreviousMinimum) ) { // La progression a ete utile, on minimise... DescenteIter++; Good = MinimizeDirection(PreviousSolution, SolSave, Sol, OldF, Delta, Tol, F_Dir); } if (!Good) { Sol = SolSave; F2 = OldF; } else { Sol = SolSave+Delta; // for (i = 1; i <= Ninc; i++) { myIsDivergent |= (Sol(i) < theInfBound(i)) | (theSupBound(i) < Sol(i)); } if (theStopOnDivergent & myIsDivergent) { return; } // Sort = Bounds(theInfBound, theSupBound, Tol, Sol, SolSave, aConstraints, Delta, isNewSol); } Sort = Standard_False; // On a rejete le point sur la frontiere } Stop = Standard_True; // et on sort dans tous les cas... } DHSave = GH; if (isNewSol) { // F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1); if(!F_Dir.Value(Sol, FF, DF, GH, F2, Gnr1)) { Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { State = F.GetStateNumber(); } return; } } Dy = GH*DH; if (Abs(Dy) <= Eps) { if (F2 > OldF) Sol = SolSave; Done = Standard_False; if (!theStopOnDivergent || !myIsDivergent) { Done = Standard_True; ////modified by jgv, 31.08.2011//// F.Value(Sol, FF); //update F before GetStateNumber /////////////////////////////////// State = F.GetStateNumber(); } return; } if (DescenteIter >= 100) { Stop = Standard_True; } } FSR_DEBUG("--- Sortie du Traitement Standard"); FSR_DEBUG(" DescenteIter = "<