From: aml Date: Mon, 18 Apr 2016 04:46:45 +0000 (+0300) Subject: 0027371: Regression: BRepExtrema works too much slower in 691 (from 670) X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=f50f030f2d3543f782f2e4c70460f0331f5148b6;p=occt-copy.git 0027371: Regression: BRepExtrema works too much slower in 691 (from 670) Lipschitz constant tuning. Shubert estimation for minimal value is added. Test case is added. --- diff --git a/src/Extrema/Extrema_GenExtCC.gxx b/src/Extrema/Extrema_GenExtCC.gxx index d81b6af1b9..473d663e85 100644 --- a/src/Extrema/Extrema_GenExtCC.gxx +++ b/src/Extrema/Extrema_GenExtCC.gxx @@ -198,8 +198,14 @@ void Extrema_GenExtCC::Perform() C1.Intervals(anIntervals1, GeomAbs_C2); C2.Intervals(anIntervals2, GeomAbs_C2); - // Lipchitz constant approximation. + // Lipchitz constant computation. Standard_Real aLC = 9.0; // Default value. + const Standard_Real aMaxDer1 = 1.0 / C1.Resolution(1.0); + const Standard_Real aMaxDer2 = 1.0 / C2.Resolution(1.0); + const Standard_Real aMaxDer = Max(aMaxDer1, aMaxDer2) * Sqrt(2.0); + if (aLC > aMaxDer) + aLC = aMaxDer; + Standard_Boolean isConstLockedFlag = Standard_False; if (C1.GetType() == GeomAbs_Line) { diff --git a/src/math/math_GlobOptMin.cxx b/src/math/math_GlobOptMin.cxx index bf75a6af71..e696d178b4 100644 --- a/src/math/math_GlobOptMin.cxx +++ b/src/math/math_GlobOptMin.cxx @@ -25,6 +25,27 @@ #include #include +//======================================================================= +//function : DistanceToBorder +//purpose : +//======================================================================= +static Standard_Real DistanceToBorder(const math_Vector & theX, + const math_Vector & theMin, + const math_Vector & theMax) +{ + Standard_Real aDist = RealLast(); + + for (Standard_Integer anIdx = theMin.Lower(); anIdx <= theMin.Upper(); ++anIdx) + { + const Standard_Real aDist1 = Abs (theX(anIdx) - theMin(anIdx)); + const Standard_Real aDist2 = Abs (theX(anIdx) - theMax(anIdx)); + + aDist = Min (aDist, Min (aDist1, aDist2)); + } + + return aDist; +} + //======================================================================= //function : math_GlobOptMin @@ -74,12 +95,6 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc, myMaxV(i) = (myB(i) - myA(i)) / 3.0; } - myExpandCoeff(1) = 1.0; - for(i = 2; i <= myN; i++) - { - myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1)); - } - myTol = theDiscretizationTol; mySameTol = theSameTol; @@ -125,12 +140,6 @@ void math_GlobOptMin::SetGlobalParams(math_MultipleVarFunction* theFunc, myMaxV(i) = (myB(i) - myA(i)) / 3.0; } - myExpandCoeff(1) = 1.0; - for(i = 2; i <= myN; i++) - { - myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1)); - } - myTol = theDiscretizationTol; mySameTol = theSameTol; @@ -161,12 +170,6 @@ void math_GlobOptMin::SetLocalParams(const math_Vector& theLocalA, myMaxV(i) = (myB(i) - myA(i)) / 3.0; } - myExpandCoeff(1) = 1.0; - for(i = 2; i <= myN; i++) - { - myExpandCoeff(i) = (myB(i) - myA(i)) / (myB(i - 1) - myA(i - 1)); - } - myDone = Standard_False; } @@ -394,18 +397,15 @@ void math_GlobOptMin::computeInitialValues() void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) { Standard_Integer i; - Standard_Real d; // Functional in moved point. + Standard_Real d = RealLast(), aPrevVal; // Functional in original and moved points. Standard_Real val = RealLast(); // Local extrema computed in moved point. Standard_Real aStepBestValue = RealLast(); math_Vector aStepBestPoint(1, myN); - Standard_Boolean isInside = Standard_False; - Standard_Real r; - Standard_Boolean isReached = Standard_False; + Standard_Boolean isInside = Standard_False, + isReached = Standard_False; + Standard_Real r1, r2, r; - - for(myX(j) = myA(j) + myE1; - (myX(j) < myB(j) + myE1) && (!isReached); - myX(j) += myV(j)) + for(myX(j) = myA(j) + myE1; !isReached; myX(j) += myV(j)) { if (myX(j) > myB(j)) { @@ -419,11 +419,30 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) if (j == 1) { isInside = Standard_False; + aPrevVal = d; myFunc->Value(myX, d); - r = (d + myZ * myC * myLastStep - myF) * myZ; + r1 = (d + myZ * myC * myLastStep - myF) * myZ; // Evtushenko estimation. + r2 = ((d + aPrevVal - myC * myLastStep) * 0.5 - myF) * myZ; // Shubert / Piyavsky estimation. + r = Min(r1, r2); if(r > myE3) { - isInside = computeLocalExtremum(myX, val, myTmp); + Standard_Real aSaveParam = myX(1); + + // Piyavsky midpoint estimation. + Standard_Real aParam = (2 * myX(1) - myV(1) ) * 0.5 + (aPrevVal - d) * 0.5 / myC; + if (Precision::IsInfinite(aPrevVal)) + aParam = myX(1) - myV(1) * 0.5; // Protection from upper dimension step. + + myX(1) = aParam; + Standard_Real aVal = 0; + myFunc->Value(myX, aVal); + myX(1) = aSaveParam; + + if ( (aVal < d && aVal < aPrevVal) || + DistanceToBorder(myX, myA, myB) < myE1 ) // Condition optimization case near the border. + { + isInside = computeLocalExtremum(myX, val, myTmp); + } } aStepBestValue = (isInside && (val < d))? val : d; aStepBestPoint = (isInside && (val < d))? myTmp : myX; @@ -478,7 +497,7 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) // Compute step in (j + 1) dimension according to scale. if (j < myN) { - Standard_Real aUpperDimStep = myV(j) * myExpandCoeff(j + 1); + Standard_Real aUpperDimStep = Max(myV(j), myE2); if (myV(j + 1) > aUpperDimStep) { if (aUpperDimStep > myMaxV(j + 1)) // Case of too big step. diff --git a/tests/bugs/fclasses/bug25635_1 b/tests/bugs/fclasses/bug25635_1 index 2ae860f420..0770219c53 100755 --- a/tests/bugs/fclasses/bug25635_1 +++ b/tests/bugs/fclasses/bug25635_1 @@ -11,7 +11,7 @@ ellipse c2 4 0 2 1 set info [2dextrema c1 c2] -set tol_abs 1.e-5 +set tol_abs 7.e-5 set tol_rel 0.01 #-1 @@ -36,7 +36,7 @@ checkreal "Parameter2" ${Parameter2} ${expected_Parameter2} ${tol_abs} ${tol_rel set expected_OriginX 2. checkreal "OriginX" ${OriginX} ${expected_OriginX} ${tol_abs} ${tol_rel} -set expected_OriginY 7.e-05 +set expected_OriginY 0.0 checkreal "OriginY" ${OriginY} ${expected_OriginY} ${tol_abs} ${tol_rel} set expected_AxisX 1. diff --git a/tests/bugs/fclasses/bug27371 b/tests/bugs/fclasses/bug27371 new file mode 100644 index 0000000000..04663ca9b1 --- /dev/null +++ b/tests/bugs/fclasses/bug27371 @@ -0,0 +1,33 @@ +puts "========" +puts "OCC27371" +puts "========" +puts "" +############################################## +# Regression: BRepExtrema works too much slower in 691 (from 670) +############################################## +restore [locate_data_file bug27371.brep] aShape +explode aShape + +cpulimit 200 + +# Check computation time +chrono h reset; chrono h start +for { set i 1 } { $i <= 100 } { incr i } { + distmini d aShape_1 aShape_2 + distmini d aShape_2 aShape_1 +} +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.2 +set aDist [dval d_val] +checkreal "Distance value check" $aDist $aDist_Exp $absTol $relTol \ No newline at end of file