mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-29 14:00:49 +03:00
0026022: Extrema_ExtCC gives not precise solution
Conditional optimization added to Newton optimization algorithm. Test case for issue CR26022
This commit is contained in:
@@ -258,8 +258,8 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt
|
||||
{
|
||||
math_MultipleVarFunctionWithHessian* myTmp =
|
||||
dynamic_cast<math_MultipleVarFunctionWithHessian*> (myFunc);
|
||||
|
||||
math_NewtonMinimum newtonMinimum(*myTmp);
|
||||
newtonMinimum.SetBoundary(myGlobA, myGlobB);
|
||||
newtonMinimum.Perform(*myTmp, thePnt);
|
||||
|
||||
if (newtonMinimum.IsDone())
|
||||
|
@@ -97,8 +97,13 @@ is
|
||||
raises DimensionError,
|
||||
NotDone
|
||||
is static;
|
||||
|
||||
|
||||
|
||||
SetBoundary(me: in out;
|
||||
theLeftBorder : in Vector;
|
||||
theRightBorder: in Vector)
|
||||
---Purpose: Set boundaries.
|
||||
is static;
|
||||
|
||||
Minimum(me)
|
||||
---Purpose: returns the value of the minimum.
|
||||
-- Exception NotDone is raised if the minimum was not found.
|
||||
@@ -166,6 +171,9 @@ CTol: Real is protected;
|
||||
nbiter: Integer is protected;
|
||||
NoConvexTreatement: Boolean is protected;
|
||||
Convex : Boolean is protected;
|
||||
myIsBoundsDefined : Boolean is protected;
|
||||
myLeft : Vector is protected;
|
||||
myRight : Vector is protected;
|
||||
Itermax: Integer;
|
||||
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//#endif
|
||||
|
||||
#include <math_NewtonMinimum.ixx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <math_Gauss.hxx>
|
||||
#include <math_Jacobi.hxx>
|
||||
@@ -49,6 +50,9 @@ math_NewtonMinimum::math_NewtonMinimum(
|
||||
nbiter (0),
|
||||
NoConvexTreatement(theWithSingularity),
|
||||
Convex (Standard_True),
|
||||
myIsBoundsDefined(Standard_False),
|
||||
myLeft(1, theFunction.NbVariables(), 0.0),
|
||||
myRight(1, theFunction.NbVariables(), 0.0),
|
||||
Done (Standard_False),
|
||||
Itermax (theNbIterations)
|
||||
{
|
||||
@@ -62,6 +66,18 @@ math_NewtonMinimum::~math_NewtonMinimum()
|
||||
{
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetBoundary
|
||||
//purpose : Set boundaries for conditional optimization
|
||||
//=======================================================================
|
||||
void math_NewtonMinimum::SetBoundary(const math_Vector& theLeftBorder,
|
||||
const math_Vector& theRightBorder)
|
||||
{
|
||||
myLeft = theLeftBorder;
|
||||
myRight = theRightBorder;
|
||||
myIsBoundsDefined = Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Perform
|
||||
//purpose :
|
||||
@@ -134,8 +150,52 @@ void math_NewtonMinimum::Perform(math_MultipleVarFunctionWithHessian& F,
|
||||
TheStatus = math_DirectionSearchError;
|
||||
return;
|
||||
}
|
||||
|
||||
LU.Solve(TheGradient, TheStep);
|
||||
|
||||
if (myIsBoundsDefined)
|
||||
{
|
||||
// Project point on bounds or nullify TheStep coords if point lies on boudary.
|
||||
|
||||
*suivant = *precedent - TheStep;
|
||||
Standard_Real aMult = RealLast();
|
||||
for(Standard_Integer anIdx = 1; anIdx <= myLeft.Upper(); anIdx++)
|
||||
{
|
||||
if (suivant->Value(anIdx) < myLeft(anIdx))
|
||||
{
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myLeft(anIdx)) / Abs(TheStep(anIdx));
|
||||
aMult = Min (aValue, aMult);
|
||||
}
|
||||
|
||||
if (suivant->Value(anIdx) > myRight(anIdx))
|
||||
{
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myRight(anIdx)) / Abs(TheStep(anIdx));
|
||||
aMult = Min (aValue, aMult);
|
||||
}
|
||||
}
|
||||
|
||||
if (aMult != RealLast())
|
||||
{
|
||||
if (aMult > Precision::PConfusion())
|
||||
{
|
||||
// Project point into param space.
|
||||
TheStep *= aMult;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old point on border and new point out of border:
|
||||
// Nullify corresponding TheStep indexes.
|
||||
for(Standard_Integer anIdx = 1; anIdx <= myLeft.Upper(); anIdx++)
|
||||
{
|
||||
if (Abs(precedent->Value(anIdx) - myRight(anIdx)) < Precision::PConfusion() ||
|
||||
Abs(precedent->Value(anIdx) - myLeft(anIdx) ) < Precision::PConfusion())
|
||||
{
|
||||
TheStep(anIdx) = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Boolean hasProblem = Standard_False;
|
||||
do
|
||||
{
|
||||
|
Reference in New Issue
Block a user