diff --git a/sc/source/solver/SlpSolver.cxx b/sc/source/solver/SlpSolver.cxx index 52ecb8862b0c..ee0b2a1dcd0f 100644 --- a/sc/source/solver/SlpSolver.cxx +++ b/sc/source/solver/SlpSolver.cxx @@ -373,6 +373,8 @@ SLPSolver::solveTrustRegionQp(const ScSolverCellHashMap& rCells, const std::vect constexpr int nMaxFrankWolfe = 50; constexpr double fGapTolerance = 1.0e-9; + constexpr double fGapFraction = 1.0e-3; + double fInitialGap = 0.0; for (int nFrankWolfe = 0; nFrankWolfe < nMaxFrankWolfe; ++nFrankWolfe) { // Gradient of the quadratic model at the current step: B d + g. @@ -399,7 +401,13 @@ SLPSolver::solveTrustRegionQp(const ScSolverCellHashMap& rCells, const std::vect // Duality gap: how much the linear model could still improve. double fGap = -dotProduct(aQuadraticGradient, aDirection); - if (fGap < fGapTolerance) + if (nFrankWolfe == 0) + fInitialGap = fGap; + // Stop once the subproblem is solved well enough: the gap has shrunk to + // a small fraction of its initial value, or below an absolute floor. + // Driving the gap all the way to zero is wasted work, because the outer + // trust-region loop re-samples and re-solves around the accepted step. + if (fGap < fGapTolerance || fGap < fGapFraction * fInitialGap) break; // Exact line search of the quadratic along the Frank-Wolfe direction.