mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0027131: [Regression to 6.7] DistShapeShape performance loss
Lipchitz constant approximation and fixes in global optimization algorithm added to improve performance. Test case added. Fix backporting: 0026593: Coding rules - revert compatibility of NCollection_CellFilter constructor with old code Restored old constructor and old behavior where possible. Minor correction. 0026395: Merge clasees NCollection_CellFilter_NDim and NCollection_CellFilter Deleted exceed class CellFilterNDim. Now dimension count used as input parameter in NCollection_CellFilter. minor corrections.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <Standard_Boolean.hxx>
|
||||
#include <BRepMesh.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
class gp_Circ2d;
|
||||
|
||||
@@ -67,7 +68,8 @@ public:
|
||||
inline void SetCellSize(const Standard_Real theSizeX,
|
||||
const Standard_Real theSizeY)
|
||||
{
|
||||
Standard_Real aCellSize[2] = { theSizeX, theSizeY };
|
||||
Standard_Real aCellSizeC[2] = { theSizeX, theSizeY };
|
||||
NCollection_Array1<Standard_Real> aCellSize(aCellSizeC[0], 1, 2);
|
||||
myCellFilter.Reset(aCellSize, myAllocator);
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#ifndef _BRepMesh_VertexTool_HeaderFile
|
||||
#define _BRepMesh_VertexTool_HeaderFile
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Macro.hxx>
|
||||
@@ -54,7 +55,8 @@ public:
|
||||
Standard_EXPORT void SetCellSize(const Standard_Real theSizeX,
|
||||
const Standard_Real theSizeY)
|
||||
{
|
||||
Standard_Real aCellSize[2] = { theSizeX, theSizeY };
|
||||
Standard_Real aCellSizeC[2] = { theSizeX, theSizeY };
|
||||
NCollection_Array1<Standard_Real> aCellSize(aCellSizeC[0], 1, 2);
|
||||
myCellFilter.Reset(aCellSize, myAllocator);
|
||||
mySelector.Clear();
|
||||
}
|
||||
|
@@ -198,12 +198,20 @@ void Extrema_GenExtCC::Perform()
|
||||
C1.Intervals(anIntervals1, GeomAbs_C2);
|
||||
C2.Intervals(anIntervals2, GeomAbs_C2);
|
||||
|
||||
// Lipchitz constant approximation.
|
||||
Standard_Real aLC = 9.0; // Default value.
|
||||
if (C1.GetType() == GeomAbs_Line)
|
||||
aLC = Min(aLC, 1.0 / C2.Resolution(1.0));
|
||||
if (C2.GetType() == GeomAbs_Line)
|
||||
aLC = Min(aLC, 1.0 / C1.Resolution(1.0));
|
||||
|
||||
Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
|
||||
math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder);
|
||||
math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
|
||||
Standard_Real aDiscTol = 1.0e-2;
|
||||
Standard_Real aValueTol = 1.0e-2;
|
||||
Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
|
||||
aFinder.SetTol(aDiscTol, aSameTol);
|
||||
aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
|
||||
|
||||
// Size computed to have cell index inside of int32 value.
|
||||
const Standard_Real aCellSize = Max(anIntervals1.Upper() - anIntervals1.Lower(),
|
||||
@@ -283,7 +291,7 @@ void Extrema_GenExtCC::Perform()
|
||||
// Check for infinity solutions case, for this:
|
||||
// Sort points lexicographically and check midpoint between each two neighboring points.
|
||||
// If all midpoints functional value is acceptable
|
||||
// then set myParallel flag to true and return one soulution.
|
||||
// then set myParallel flag to true and return one solution.
|
||||
std::sort(aPnts.begin(), aPnts.end(), comp);
|
||||
Standard_Boolean isParallel = Standard_False;
|
||||
Standard_Real aVal = 0.0;
|
||||
|
@@ -17,6 +17,8 @@
|
||||
#define NCollection_CellFilter_HeaderFile
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <NCollection_LocalArray.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <NCollection_Map.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
@@ -110,37 +112,39 @@ enum NCollection_CellFilter_Action
|
||||
* Note that method Inspect() can be const and/or virtual.
|
||||
*/
|
||||
|
||||
template <class Inspector>
|
||||
class NCollection_CellFilter
|
||||
{
|
||||
template <class Inspector> class NCollection_CellFilter
|
||||
{
|
||||
public:
|
||||
typedef TYPENAME Inspector::Target Target;
|
||||
typedef TYPENAME Inspector::Point Point;
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor; initialized by cell size.
|
||||
//! Constructor; initialized by dimension count and cell size.
|
||||
//!
|
||||
//! Note: the cell size must be ensured to be greater than
|
||||
//! Note: the cell size must be ensured to be greater than
|
||||
//! maximal co-ordinate of the involved points divided by INT_MAX,
|
||||
//! in order to avoid integer overflow of cell index.
|
||||
//!
|
||||
//! By default cell size is 0, which is invalid; thus if default
|
||||
//! constructor is used, the tool must be initialized later with
|
||||
//! appropriate cell size by call to Reset()
|
||||
NCollection_CellFilter (Standard_Real theCellSize=0,
|
||||
const Handle(NCollection_IncAllocator)& theAlloc=0)
|
||||
//! Constructor when dimension count is unknown at compilation time.
|
||||
NCollection_CellFilter (const Standard_Integer theDim,
|
||||
const Standard_Real theCellSize = 0,
|
||||
const Handle(NCollection_IncAllocator)& theAlloc = 0)
|
||||
: myCellSize(0, theDim - 1)
|
||||
{
|
||||
myDim = theDim;
|
||||
Reset (theCellSize, theAlloc);
|
||||
}
|
||||
|
||||
//! Constructor; initialized by cell sizes along each dimension.
|
||||
//! Note: the cell size in each dimension must be ensured to be greater than
|
||||
//! maximal co-ordinate of the involved points by this dimension divided by INT_MAX,
|
||||
//! in order to avoid integer overflow of cell index.
|
||||
NCollection_CellFilter (Standard_Real theCellSize[],
|
||||
const Handle(NCollection_IncAllocator)& theAlloc=0)
|
||||
//! Constructor when dimenstion count is known at compilation time.
|
||||
NCollection_CellFilter (const Standard_Real theCellSize = 0,
|
||||
const Handle(NCollection_IncAllocator)& theAlloc = 0)
|
||||
: myCellSize(0, Inspector::Dimension - 1)
|
||||
{
|
||||
myDim = Inspector::Dimension;
|
||||
Reset (theCellSize, theAlloc);
|
||||
}
|
||||
|
||||
@@ -148,17 +152,16 @@ public:
|
||||
void Reset (Standard_Real theCellSize,
|
||||
const Handle(NCollection_IncAllocator)& theAlloc=0)
|
||||
{
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
myCellSize[i] = theCellSize;
|
||||
for (int i=0; i < myDim; i++)
|
||||
myCellSize(i) = theCellSize;
|
||||
resetAllocator ( theAlloc );
|
||||
}
|
||||
|
||||
//! Clear the data structures and set new cell sizes and allocator
|
||||
void Reset (Standard_Real theCellSize[],
|
||||
void Reset (NCollection_Array1<Standard_Real> theCellSize,
|
||||
const Handle(NCollection_IncAllocator)& theAlloc=0)
|
||||
{
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
myCellSize[i] = theCellSize[i];
|
||||
myCellSize = theCellSize;
|
||||
resetAllocator ( theAlloc );
|
||||
}
|
||||
|
||||
@@ -180,7 +183,7 @@ public:
|
||||
Cell aCellMax (thePntMax, myCellSize);
|
||||
Cell aCell = aCellMin;
|
||||
// add object recursively into all cells in range
|
||||
iterateAdd (Inspector::Dimension-1, aCell, aCellMin, aCellMax, theTarget);
|
||||
iterateAdd (myDim-1, aCell, aCellMin, aCellMax, theTarget);
|
||||
}
|
||||
|
||||
//! Find a target object at a point and remove it from the structures.
|
||||
@@ -204,7 +207,7 @@ public:
|
||||
Cell aCellMax (thePntMax, myCellSize);
|
||||
Cell aCell = aCellMin;
|
||||
// remove object recursively from all cells in range
|
||||
iterateRemove (Inspector::Dimension-1, aCell, aCellMin, aCellMax, theTarget);
|
||||
iterateRemove (myDim-1, aCell, aCellMin, aCellMax, theTarget);
|
||||
}
|
||||
|
||||
//! Inspect all targets in the cell corresponding to the given point
|
||||
@@ -225,7 +228,7 @@ public:
|
||||
Cell aCellMax (thePntMax, myCellSize);
|
||||
Cell aCell = aCellMin;
|
||||
// inspect object recursively into all cells in range
|
||||
iterateInspect (Inspector::Dimension-1, aCell,
|
||||
iterateInspect (myDim-1, aCell,
|
||||
aCellMin, aCellMax, theInspector);
|
||||
}
|
||||
|
||||
@@ -238,7 +241,14 @@ protected:
|
||||
/**
|
||||
* Auxiliary class for storing points belonging to the cell as the list
|
||||
*/
|
||||
struct ListNode {
|
||||
struct ListNode
|
||||
{
|
||||
ListNode()
|
||||
{
|
||||
// Empty constructor is forbidden.
|
||||
Standard_NoSuchObject::Raise("NCollection_CellFilter::ListNode()");
|
||||
}
|
||||
|
||||
Target Object;
|
||||
ListNode *Next;
|
||||
};
|
||||
@@ -251,17 +261,16 @@ protected:
|
||||
struct Cell
|
||||
{
|
||||
public:
|
||||
//! Empty constructor -- required only for NCollection_Map,
|
||||
//! therefore does not initialize index (avoid cycle)
|
||||
Cell () : Objects(0) {}
|
||||
|
||||
//! Constructor; computes cell indices
|
||||
Cell (const Point& thePnt, const Standard_Real theCellSize[])
|
||||
: Objects(0)
|
||||
Cell (const Point& thePnt,
|
||||
const NCollection_Array1<Standard_Real>& theCellSize)
|
||||
: index(theCellSize.Size()),
|
||||
Objects(0)
|
||||
{
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
for (int i = 0; i < theCellSize.Size(); i++)
|
||||
{
|
||||
Standard_Real val = (Standard_Real)(Inspector::Coord(i, thePnt) / theCellSize[i]);
|
||||
Standard_Real val = (Standard_Real)(Inspector::Coord(i, thePnt) / theCellSize(theCellSize.Lower() + i));
|
||||
//If the value of index is greater than
|
||||
//INT_MAX it is decreased correspondingly for the value of INT_MAX. If the value
|
||||
//of index is less than INT_MIN it is increased correspondingly for the absolute
|
||||
@@ -273,13 +282,19 @@ protected:
|
||||
}
|
||||
|
||||
//! Copy constructor: ensure that list is not deleted twice
|
||||
Cell (const Cell& theOther) { (*this) = theOther; }
|
||||
Cell (const Cell& theOther)
|
||||
: index(theOther.index.Size())
|
||||
{
|
||||
(*this) = theOther;
|
||||
}
|
||||
|
||||
//! Assignment operator: ensure that list is not deleted twice
|
||||
void operator = (const Cell& theOther)
|
||||
{
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
index[i] = theOther.index[i];
|
||||
Standard_Integer myDim = Standard_Integer(theOther.index.Size());
|
||||
for(Standard_Integer anIdx = 0; anIdx < myDim; anIdx++)
|
||||
index[anIdx] = theOther.index[anIdx];
|
||||
|
||||
Objects = theOther.Objects;
|
||||
((Cell&)theOther).Objects = 0;
|
||||
}
|
||||
@@ -296,7 +311,8 @@ protected:
|
||||
//! Compare cell with other one
|
||||
Standard_Boolean IsEqual (const Cell& theOther) const
|
||||
{
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
Standard_Integer myDim = Standard_Integer(theOther.index.Size());
|
||||
for (int i=0; i < myDim; i++)
|
||||
if ( index[i] != theOther.index[i] ) return Standard_False;
|
||||
return Standard_True;
|
||||
}
|
||||
@@ -305,15 +321,16 @@ protected:
|
||||
Standard_Integer HashCode (const Standard_Integer theUpper) const
|
||||
{
|
||||
// number of bits per each dimension in the hash code
|
||||
const Standard_Size aShiftBits = (BITS(long)-1) / Inspector::Dimension;
|
||||
Standard_Integer myDim = Standard_Integer(index.Size());
|
||||
const Standard_Size aShiftBits = (BITS(long)-1) / myDim;
|
||||
long aCode=0;
|
||||
for (int i=0; i < Inspector::Dimension; i++)
|
||||
for (int i=0; i < myDim; i++)
|
||||
aCode = ( aCode << aShiftBits ) ^ index[i];
|
||||
return (unsigned)aCode % theUpper;
|
||||
}
|
||||
|
||||
public:
|
||||
long index[Inspector::Dimension];
|
||||
NCollection_LocalArray<long, 10> index;
|
||||
ListNode *Objects;
|
||||
};
|
||||
|
||||
@@ -452,9 +469,10 @@ protected:
|
||||
}
|
||||
|
||||
protected:
|
||||
Standard_Integer myDim;
|
||||
Handle(NCollection_BaseAllocator) myAllocator;
|
||||
NCollection_Map<Cell> myCells;
|
||||
Standard_Real myCellSize [Inspector::Dimension];
|
||||
NCollection_Array1<Standard_Real> myCellSize;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -504,4 +522,3 @@ struct NCollection_CellFilter_InspectorXY
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -20,13 +20,10 @@
|
||||
|
||||
//! Auxiliary class optimizing creation of array buffer
|
||||
//! (using stack allocation for small arrays).
|
||||
template<class theItem> class NCollection_LocalArray
|
||||
template<class theItem, Standard_Integer MAX_ARRAY_SIZE = 1024> class NCollection_LocalArray
|
||||
{
|
||||
public:
|
||||
|
||||
// 1K * sizeof (theItem)
|
||||
static const size_t MAX_ARRAY_SIZE = 1024;
|
||||
|
||||
NCollection_LocalArray (const size_t theSize)
|
||||
: myPtr (myBuffer)
|
||||
{
|
||||
@@ -34,7 +31,7 @@ public:
|
||||
}
|
||||
|
||||
NCollection_LocalArray ()
|
||||
: myPtr (myBuffer) {}
|
||||
: myPtr (myBuffer), mySize(0) {}
|
||||
|
||||
~NCollection_LocalArray()
|
||||
{
|
||||
@@ -48,6 +45,13 @@ public:
|
||||
myPtr = (theItem*)Standard::Allocate (theSize * sizeof(theItem));
|
||||
else
|
||||
myPtr = myBuffer;
|
||||
|
||||
mySize = theSize;
|
||||
}
|
||||
|
||||
size_t Size() const
|
||||
{
|
||||
return mySize;
|
||||
}
|
||||
|
||||
operator theItem*() const
|
||||
@@ -72,6 +76,7 @@ protected:
|
||||
|
||||
theItem myBuffer[MAX_ARRAY_SIZE];
|
||||
theItem* myPtr;
|
||||
size_t mySize;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// Created on: 2014-01-20
|
||||
// Created by: Alexaner Malyshev
|
||||
// Copyright (c) 2014-2014 OPEN CASCADE SAS
|
||||
// Copyright (c) 2014-2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -45,13 +45,17 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc,
|
||||
myTmp(1, myN),
|
||||
myV(1, myN),
|
||||
myMaxV(1, myN),
|
||||
myExpandCoeff(1, myN)
|
||||
myExpandCoeff(1, myN),
|
||||
myCellSize(0, myN - 1),
|
||||
myFilter(theFunc->NbVariables())
|
||||
{
|
||||
Standard_Integer i;
|
||||
|
||||
myFunc = theFunc;
|
||||
myC = theC;
|
||||
myInitC = theC;
|
||||
myIsFindSingleSolution = Standard_False;
|
||||
myFunctionalMinimalValue = -Precision::Infinite();
|
||||
myZ = -1;
|
||||
mySolCount = 0;
|
||||
|
||||
@@ -78,12 +82,18 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc,
|
||||
myTol = theDiscretizationTol;
|
||||
mySameTol = theSameTol;
|
||||
|
||||
const Standard_Integer aMaxSquareSearchSol = 200;
|
||||
Standard_Integer aSolNb = Standard_Integer(Pow(3.0, Standard_Real(myN)));
|
||||
myMinCellFilterSol = Max(2 * aSolNb, aMaxSquareSearchSol);
|
||||
initCellSize();
|
||||
ComputeInitSol();
|
||||
|
||||
myDone = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetGlobalParams
|
||||
//purpose : Set params without memory allocation.
|
||||
//purpose : Set parameters without memory allocation.
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::SetGlobalParams(math_MultipleVarFunction* theFunc,
|
||||
const math_Vector& theA,
|
||||
@@ -96,6 +106,7 @@ void math_GlobOptMin::SetGlobalParams(math_MultipleVarFunction* theFunc,
|
||||
|
||||
myFunc = theFunc;
|
||||
myC = theC;
|
||||
myInitC = theC;
|
||||
myZ = -1;
|
||||
mySolCount = 0;
|
||||
|
||||
@@ -122,12 +133,15 @@ void math_GlobOptMin::SetGlobalParams(math_MultipleVarFunction* theFunc,
|
||||
myTol = theDiscretizationTol;
|
||||
mySameTol = theSameTol;
|
||||
|
||||
initCellSize();
|
||||
ComputeInitSol();
|
||||
|
||||
myDone = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetLocalParams
|
||||
//purpose : Set params without memory allocation.
|
||||
//purpose : Set parameters without memory allocation.
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::SetLocalParams(const math_Vector& theLocalA,
|
||||
const math_Vector& theLocalB)
|
||||
@@ -135,8 +149,6 @@ void math_GlobOptMin::SetLocalParams(const math_Vector& theLocalA,
|
||||
Standard_Integer i;
|
||||
|
||||
myZ = -1;
|
||||
mySolCount = 0;
|
||||
|
||||
for(i = 1; i <= myN; i++)
|
||||
{
|
||||
myA(i) = theLocalA(i);
|
||||
@@ -217,7 +229,7 @@ void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution)
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute initial values for myF, myY, myC.
|
||||
// Compute initial value for myC.
|
||||
computeInitialValues();
|
||||
|
||||
myE1 = minLength * myTol;
|
||||
@@ -238,6 +250,14 @@ void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution)
|
||||
myE3 = - maxLength * myTol * myC / 4.0;
|
||||
}
|
||||
|
||||
// Search single solution and current solution in its neighborhood.
|
||||
if (CheckFunctionalStopCriteria())
|
||||
{
|
||||
myDone = Standard_True;
|
||||
return;
|
||||
}
|
||||
|
||||
isFirstCellFilterInvoke = Standard_True;
|
||||
computeGlobalExtremum(myN);
|
||||
|
||||
myDone = Standard_True;
|
||||
@@ -256,11 +276,11 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt
|
||||
//Newton method
|
||||
if (dynamic_cast<math_MultipleVarFunctionWithHessian*>(myFunc))
|
||||
{
|
||||
math_MultipleVarFunctionWithHessian* myTmp =
|
||||
math_MultipleVarFunctionWithHessian* aTmp =
|
||||
dynamic_cast<math_MultipleVarFunctionWithHessian*> (myFunc);
|
||||
math_NewtonMinimum newtonMinimum(*myTmp);
|
||||
math_NewtonMinimum newtonMinimum(*aTmp);
|
||||
newtonMinimum.SetBoundary(myGlobA, myGlobB);
|
||||
newtonMinimum.Perform(*myTmp, thePnt);
|
||||
newtonMinimum.Perform(*aTmp, thePnt);
|
||||
|
||||
if (newtonMinimum.IsDone())
|
||||
{
|
||||
@@ -273,10 +293,10 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt
|
||||
// BFGS method used.
|
||||
if (dynamic_cast<math_MultipleVarFunctionWithGradient*>(myFunc))
|
||||
{
|
||||
math_MultipleVarFunctionWithGradient* myTmp =
|
||||
math_MultipleVarFunctionWithGradient* aTmp =
|
||||
dynamic_cast<math_MultipleVarFunctionWithGradient*> (myFunc);
|
||||
math_BFGS bfgs(myTmp->NbVariables());
|
||||
bfgs.Perform(*myTmp, thePnt);
|
||||
math_BFGS bfgs(aTmp->NbVariables());
|
||||
bfgs.Perform(*aTmp, thePnt);
|
||||
if (bfgs.IsDone())
|
||||
{
|
||||
bfgs.Location(theOutPnt);
|
||||
@@ -320,35 +340,8 @@ void math_GlobOptMin::computeInitialValues()
|
||||
math_Vector aBestPnt(1, myN);
|
||||
math_Vector aParamStep(1, myN);
|
||||
Standard_Real aCurrVal = RealLast();
|
||||
Standard_Real aBestVal = RealLast();
|
||||
|
||||
// Check functional value in midpoint, low and upp point border and
|
||||
// in each point try to perform local optimization.
|
||||
aBestPnt = (myA + myB) * 0.5;
|
||||
myFunc->Value(aBestPnt, aBestVal);
|
||||
|
||||
for(i = 1; i <= 3; i++)
|
||||
{
|
||||
aCurrPnt = myA + (myB - myA) * (i - 1) / 2.0;
|
||||
|
||||
if(computeLocalExtremum(aCurrPnt, aCurrVal, aCurrPnt))
|
||||
{
|
||||
// Local Extremum finds better solution than current point.
|
||||
if (aCurrVal < aBestVal)
|
||||
{
|
||||
aBestVal = aCurrVal;
|
||||
aBestPnt = aCurrPnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myF = aBestVal;
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aBestPnt(i));
|
||||
mySolCount++;
|
||||
|
||||
// Lipschitz const approximation
|
||||
// Lipchitz const approximation.
|
||||
Standard_Real aLipConst = 0.0, aPrevValDiag, aPrevValProj;
|
||||
Standard_Integer aPntNb = 13;
|
||||
myFunc->Value(myA, aPrevValDiag);
|
||||
@@ -371,16 +364,23 @@ void math_GlobOptMin::computeInitialValues()
|
||||
aPrevValProj = aCurrVal;
|
||||
}
|
||||
|
||||
myC = myInitC;
|
||||
aLipConst *= Sqrt(myN) / aStep;
|
||||
|
||||
if (aLipConst < myC * 0.1)
|
||||
{
|
||||
myC = Max(aLipConst * 0.1, 0.01);
|
||||
}
|
||||
else if (aLipConst > myC * 10)
|
||||
{
|
||||
myC = Min(myC * 2, 30.0);
|
||||
|
||||
// Clear all solutions except one.
|
||||
if (myY.Size() != myN)
|
||||
{
|
||||
for(i = 1; i <= myN; i++)
|
||||
aBestPnt(i) = myY(i);
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aBestPnt(i));
|
||||
}
|
||||
mySolCount = 1;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -399,7 +399,8 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
|
||||
Standard_Real r;
|
||||
Standard_Boolean isReached = Standard_False;
|
||||
|
||||
for(myX(j) = myA(j) + myE1;
|
||||
|
||||
for(myX(j) = myA(j) + myE1;
|
||||
(myX(j) < myB(j) + myE1) && (!isReached);
|
||||
myX(j) += myV(j))
|
||||
{
|
||||
@@ -409,11 +410,14 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
|
||||
isReached = Standard_True;
|
||||
}
|
||||
|
||||
if (CheckFunctionalStopCriteria())
|
||||
return; // Best possible value is obtained.
|
||||
|
||||
if (j == 1)
|
||||
{
|
||||
isInside = Standard_False;
|
||||
myFunc->Value(myX, d);
|
||||
r = (d + myZ * myC * aRealStep - myF) * myZ;
|
||||
r = (d + myZ * myC * myV(1) - myF) * myZ;
|
||||
if(r > myE3)
|
||||
{
|
||||
isInside = computeLocalExtremum(myX, val, myTmp);
|
||||
@@ -449,8 +453,13 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aStepBestPoint(i));
|
||||
mySolCount++;
|
||||
|
||||
isFirstCellFilterInvoke = Standard_True;
|
||||
}
|
||||
|
||||
if (CheckFunctionalStopCriteria())
|
||||
return; // Best possible value is obtained.
|
||||
|
||||
aRealStep = myE2 + Abs(myF - d) / myC;
|
||||
myV(1) = Min(aRealStep, myMaxV(1));
|
||||
}
|
||||
@@ -505,20 +514,55 @@ Standard_Boolean math_GlobOptMin::isStored(const math_Vector& thePnt)
|
||||
math_Vector aTol(1, myN);
|
||||
aTol = (myB - myA) * mySameTol;
|
||||
|
||||
for(i = 0; i < mySolCount; i++)
|
||||
// C1 * n^2 = C2 * 3^dim * n
|
||||
if (mySolCount < myMinCellFilterSol)
|
||||
{
|
||||
isSame = Standard_True;
|
||||
for(j = 1; j <= myN; j++)
|
||||
for(i = 0; i < mySolCount; i++)
|
||||
{
|
||||
if ((Abs(thePnt(j) - myY(i * myN + j))) > aTol(j))
|
||||
isSame = Standard_True;
|
||||
for(j = 1; j <= myN; j++)
|
||||
{
|
||||
isSame = Standard_False;
|
||||
break;
|
||||
if ((Abs(thePnt(j) - myY(i * myN + j))) > aTol(j))
|
||||
{
|
||||
isSame = Standard_False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSame == Standard_True)
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NCollection_CellFilter_Inspector anInspector(myN, Precision::PConfusion());
|
||||
if (isFirstCellFilterInvoke)
|
||||
{
|
||||
myFilter.Reset(myCellSize);
|
||||
|
||||
// Copy initial data into cell filter.
|
||||
for(Standard_Integer aSolIdx = 0; aSolIdx < mySolCount; aSolIdx++)
|
||||
{
|
||||
math_Vector aVec(1, myN);
|
||||
for(Standard_Integer aSolDim = 1; aSolDim <= myN; aSolDim++)
|
||||
aVec(aSolDim) = myY(aSolIdx * myN + aSolDim);
|
||||
|
||||
myFilter.Add(aVec, aVec);
|
||||
}
|
||||
}
|
||||
if (isSame == Standard_True)
|
||||
return Standard_True;
|
||||
|
||||
isFirstCellFilterInvoke = Standard_False;
|
||||
|
||||
math_Vector aLow(1, myN), anUp(1, myN);
|
||||
anInspector.Shift(thePnt, myCellSize, aLow, anUp);
|
||||
|
||||
anInspector.ClearFind();
|
||||
anInspector.SetCurrent(thePnt);
|
||||
myFilter.Inspect(aLow, anUp, anInspector);
|
||||
if (!anInspector.isFind())
|
||||
{
|
||||
// Point is out of close cells, add new one.
|
||||
myFilter.Add(thePnt, thePnt);
|
||||
}
|
||||
}
|
||||
return Standard_False;
|
||||
}
|
||||
@@ -541,6 +585,24 @@ Standard_Real math_GlobOptMin::GetF()
|
||||
return myF;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetFunctionalMinimalValue
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::SetFunctionalMinimalValue(const Standard_Real theMinimalValue)
|
||||
{
|
||||
myFunctionalMinimalValue = theMinimalValue;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetFunctionalMinimalValue
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Real math_GlobOptMin::GetFunctionalMinimalValue()
|
||||
{
|
||||
return myFunctionalMinimalValue;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IsDone
|
||||
//purpose :
|
||||
@@ -561,3 +623,70 @@ void math_GlobOptMin::Points(const Standard_Integer theIndex, math_Vector& theSo
|
||||
for(j = 1; j <= myN; j++)
|
||||
theSol(j) = myY((theIndex - 1) * myN + j);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : initCellSize
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::initCellSize()
|
||||
{
|
||||
for(Standard_Integer anIdx = 1; anIdx <= myN; anIdx++)
|
||||
{
|
||||
myCellSize(anIdx - 1) = (myGlobB(anIdx) - myGlobA(anIdx))
|
||||
* Precision::PConfusion() / (2.0 * Sqrt(2.0));
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : CheckFunctionalStopCriteria
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean math_GlobOptMin::CheckFunctionalStopCriteria()
|
||||
{
|
||||
// Search single solution and current solution in its neighborhood.
|
||||
if (myIsFindSingleSolution &&
|
||||
Abs (myF - myFunctionalMinimalValue) < mySameTol * 0.01)
|
||||
return Standard_True;
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ComputeInitSol
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void math_GlobOptMin::ComputeInitSol()
|
||||
{
|
||||
Standard_Real aCurrVal, aBestVal;
|
||||
math_Vector aCurrPnt(1, myN);
|
||||
math_Vector aBestPnt(1, myN);
|
||||
math_Vector aParamStep(1, myN);
|
||||
// Check functional value in midpoint, lower and upper border points and
|
||||
// in each point try to perform local optimization.
|
||||
aBestPnt = (myGlobA + myGlobB) * 0.5;
|
||||
myFunc->Value(aBestPnt, aBestVal);
|
||||
|
||||
Standard_Integer i;
|
||||
for(i = 1; i <= 3; i++)
|
||||
{
|
||||
aCurrPnt = myA + (myB - myA) * (i - 1) / 2.0;
|
||||
|
||||
if(computeLocalExtremum(aCurrPnt, aCurrVal, aCurrPnt))
|
||||
{
|
||||
// Local search tries to find better solution than current point.
|
||||
if (aCurrVal < aBestVal)
|
||||
{
|
||||
aBestVal = aCurrVal;
|
||||
aBestPnt = aCurrPnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myF = aBestVal;
|
||||
myY.Clear();
|
||||
for(i = 1; i <= myN; i++)
|
||||
myY.Append(aBestPnt(i));
|
||||
mySolCount = 1;
|
||||
|
||||
myDone = Standard_False;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// Created on: 2014-01-20
|
||||
// Created by: Alexaner Malyshev
|
||||
// Copyright (c) 2014-2014 OPEN CASCADE SAS
|
||||
// Copyright (c) 2014-2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -16,10 +16,86 @@
|
||||
#ifndef _math_GlobOptMin_HeaderFile
|
||||
#define _math_GlobOptMin_HeaderFile
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <NCollection_CellFilter.hxx>
|
||||
#include <math_MultipleVarFunction.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
class NCollection_CellFilter_Inspector
|
||||
{
|
||||
public:
|
||||
|
||||
//! Points and target type
|
||||
typedef math_Vector Point;
|
||||
typedef math_Vector Target;
|
||||
|
||||
NCollection_CellFilter_Inspector(const Standard_Integer theDim,
|
||||
const Standard_Real theTol)
|
||||
: myCurrent(1, theDim)
|
||||
{
|
||||
myTol = theTol * theTol;
|
||||
myIsFind = Standard_False;
|
||||
Dimension = theDim;
|
||||
}
|
||||
|
||||
//! Access to co-ordinate
|
||||
static Standard_Real Coord (int i, const Point &thePnt)
|
||||
{
|
||||
return thePnt(i + 1);
|
||||
}
|
||||
|
||||
//! Auxiliary method to shift point by each coordinate on given value;
|
||||
//! useful for preparing a points range for Inspect with tolerance
|
||||
void Shift (const Point& thePnt,
|
||||
const NCollection_Array1<Standard_Real> &theTol,
|
||||
Point& theLowPnt,
|
||||
Point& theUppPnt) const
|
||||
{
|
||||
for(Standard_Integer anIdx = 1; anIdx <= Dimension; anIdx++)
|
||||
{
|
||||
theLowPnt(anIdx) = thePnt(anIdx) - theTol(anIdx - 1);
|
||||
theUppPnt(anIdx) = thePnt(anIdx) + theTol(anIdx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearFind()
|
||||
{
|
||||
myIsFind = Standard_False;
|
||||
}
|
||||
|
||||
Standard_Boolean isFind()
|
||||
{
|
||||
return myIsFind;
|
||||
}
|
||||
|
||||
//! Set current point to search for coincidence
|
||||
void SetCurrent (const math_Vector& theCurPnt)
|
||||
{
|
||||
myCurrent = theCurPnt;
|
||||
}
|
||||
|
||||
//! Implementation of inspection method
|
||||
NCollection_CellFilter_Action Inspect (const Target& theObject)
|
||||
{
|
||||
Standard_Real aSqDist = (myCurrent - theObject).Norm2();
|
||||
|
||||
if(aSqDist < myTol)
|
||||
{
|
||||
myIsFind = Standard_True;
|
||||
}
|
||||
|
||||
return CellFilter_Keep;
|
||||
}
|
||||
|
||||
private:
|
||||
Standard_Real myTol;
|
||||
math_Vector myCurrent;
|
||||
Standard_Boolean myIsFind;
|
||||
Standard_Integer Dimension;
|
||||
};
|
||||
|
||||
//! This class represents Evtushenko's algorithm of global optimization based on nonuniform mesh.<br>
|
||||
//! Article: Yu. Evtushenko. Numerical methods for finding global extreme (case of a non-uniform mesh). <br>
|
||||
//! U.S.S.R. Comput. Maths. Math. Phys., Vol. 11, N 6, pp. 38-54.
|
||||
@@ -65,16 +141,32 @@ public:
|
||||
//! Return solution theIndex, 1 <= theIndex <= NbExtrema.
|
||||
Standard_EXPORT void Points(const Standard_Integer theIndex, math_Vector& theSol);
|
||||
|
||||
Standard_Boolean isDone();
|
||||
Standard_EXPORT Standard_Boolean isDone();
|
||||
|
||||
//! Set functional minimal value.
|
||||
Standard_EXPORT void SetFunctionalMinimalValue(const Standard_Real theMinimalValue);
|
||||
|
||||
//! Get functional minimal value.
|
||||
Standard_EXPORT Standard_Real GetFunctionalMinimalValue();
|
||||
|
||||
private:
|
||||
|
||||
// Compute cell size.
|
||||
void initCellSize();
|
||||
|
||||
// Compute initial solution
|
||||
void ComputeInitSol();
|
||||
|
||||
math_GlobOptMin & operator = (const math_GlobOptMin & theOther);
|
||||
|
||||
Standard_Boolean computeLocalExtremum(const math_Vector& thePnt, Standard_Real& theVal, math_Vector& theOutPnt);
|
||||
|
||||
void computeGlobalExtremum(Standard_Integer theIndex);
|
||||
|
||||
//! Check possibility to stop computations.
|
||||
//! Find single solution + in neighbourhood of best possible solution.
|
||||
Standard_Boolean CheckFunctionalStopCriteria();
|
||||
|
||||
//! Computes starting value / approximation:
|
||||
//! myF - initial best value.
|
||||
//! myY - initial best point.
|
||||
@@ -99,8 +191,10 @@ private:
|
||||
Standard_Real mySameTol; // points with ||p1 - p2|| < mySameTol is equal,
|
||||
// function values |val1 - val2| * 0.01 < mySameTol is equal,
|
||||
// default value is 1.0e-7.
|
||||
Standard_Real myC; //Lipschitz constant, default 9
|
||||
Standard_Real myC; //Lipchitz constant, default 9
|
||||
Standard_Real myInitC; // Lipchitz constant initial value.
|
||||
Standard_Boolean myIsFindSingleSolution; // Default value is false.
|
||||
Standard_Real myFunctionalMinimalValue; // Default value is -Precision::Infinite
|
||||
|
||||
// Output.
|
||||
Standard_Boolean myDone;
|
||||
@@ -119,6 +213,11 @@ private:
|
||||
math_Vector myMaxV; // Max Steps array.
|
||||
math_Vector myExpandCoeff; // Define expand coefficient between neighboring indiced dimensions.
|
||||
|
||||
NCollection_Array1<Standard_Real> myCellSize;
|
||||
Standard_Integer myMinCellFilterSol;
|
||||
Standard_Boolean isFirstCellFilterInvoke;
|
||||
NCollection_CellFilter<NCollection_CellFilter_Inspector> myFilter;
|
||||
|
||||
Standard_Real myF; // Current value of Global optimum.
|
||||
};
|
||||
|
||||
|
32
tests/bugs/fclasses/bug27131
Normal file
32
tests/bugs/fclasses/bug27131
Normal file
@@ -0,0 +1,32 @@
|
||||
puts "========"
|
||||
puts "OCC27131"
|
||||
puts "========"
|
||||
puts ""
|
||||
##############################################
|
||||
# DistShapeShape works slow on attached shapes
|
||||
##############################################
|
||||
restore [locate_data_file bug27131.brep] aShape
|
||||
explode aShape
|
||||
|
||||
cpulimit 20
|
||||
|
||||
# Check computation time
|
||||
chrono h reset; chrono h start
|
||||
for { set i 1 } { $i <= 100 } { incr i } {
|
||||
distmini d aShape_1 aShape_2
|
||||
}
|
||||
chrono h stop; chrono h show
|
||||
|
||||
regexp {CPU user time: (\d*)} [dchrono h show] dummy sec
|
||||
if {$sec > 1} {
|
||||
puts "Error: too long computation time $sec seconds"
|
||||
} else {
|
||||
puts "Computation time is OK"
|
||||
}
|
||||
|
||||
# Check result of distance distance
|
||||
set absTol 1.0e-10
|
||||
set relTol 0.001
|
||||
set aDist_Exp 0.0029087110153708622
|
||||
set aDist [dval d_val]
|
||||
checkreal "Distance value check" $aDist $aDist_Exp $absTol $relTol
|
Reference in New Issue
Block a user