File indexing completed on 2026-09-28 09:20:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _MathOpt_BFGS_HeaderFile
0015 #define _MathOpt_BFGS_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <MathUtils_Core.hxx>
0020 #include <MathUtils_LineSearch.hxx>
0021 #include <MathUtils_Deriv.hxx>
0022
0023 #include <NCollection_DynamicArray.hxx>
0024
0025 #include <cmath>
0026
0027 namespace MathOpt
0028 {
0029 using namespace MathUtils;
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 template <typename Function>
0058 VectorResult BFGS(Function& theFunc,
0059 const math_Vector& theStartingPoint,
0060 const Config& theConfig = Config())
0061 {
0062 VectorResult aResult;
0063
0064 const int aLower = theStartingPoint.Lower();
0065 const int aUpper = theStartingPoint.Upper();
0066 const int aN = aUpper - aLower + 1;
0067
0068
0069 math_Vector aX(aLower, aUpper);
0070 aX = theStartingPoint;
0071
0072 double aFx = 0.0;
0073 if (!theFunc.Value(aX, aFx))
0074 {
0075 aResult.Status = Status::NumericalError;
0076 return aResult;
0077 }
0078
0079
0080 math_Vector aGrad(aLower, aUpper);
0081 if (!theFunc.Gradient(aX, aGrad))
0082 {
0083 aResult.Status = Status::NumericalError;
0084 return aResult;
0085 }
0086
0087
0088 double aGradNorm = 0.0;
0089 for (int i = aLower; i <= aUpper; ++i)
0090 {
0091 aGradNorm += MathUtils::Sqr(aGrad(i));
0092 }
0093 aGradNorm = std::sqrt(aGradNorm);
0094
0095 if (aGradNorm < theConfig.FTolerance)
0096 {
0097 aResult.Status = Status::OK;
0098 aResult.Solution = aX;
0099 aResult.Value = aFx;
0100 aResult.Gradient = aGrad;
0101 return aResult;
0102 }
0103
0104
0105 math_Matrix aH(1, aN, 1, aN, 0.0);
0106 for (int i = 1; i <= aN; ++i)
0107 {
0108 aH(i, i) = 1.0;
0109 }
0110
0111
0112 math_Vector aDir(aLower, aUpper);
0113 math_Vector aXNew(aLower, aUpper);
0114 math_Vector aGradNew(aLower, aUpper);
0115 math_Vector aS(1, aN);
0116 math_Vector aY(1, aN);
0117
0118 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0119 {
0120 aResult.NbIterations = anIter + 1;
0121
0122
0123 for (int i = 1; i <= aN; ++i)
0124 {
0125 double aSum = 0.0;
0126 for (int j = 1; j <= aN; ++j)
0127 {
0128 aSum += aH(i, j) * aGrad(aLower + j - 1);
0129 }
0130 aDir(aLower + i - 1) = -aSum;
0131 }
0132
0133
0134 MathUtils::LineSearchResult aLineResult =
0135 MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, 1.0, 1.0e-4, 0.5, 50);
0136
0137 if (!aLineResult.IsValid || aLineResult.Alpha < MathUtils::THE_EPSILON)
0138 {
0139
0140 for (int i = aLower; i <= aUpper; ++i)
0141 {
0142 aDir(i) = -aGrad(i);
0143 }
0144 aLineResult = MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, 1.0, 1.0e-4, 0.5, 50);
0145
0146 if (!aLineResult.IsValid)
0147 {
0148
0149 aResult.Status = Status::NotConverged;
0150 aResult.Solution = aX;
0151 aResult.Value = aFx;
0152 aResult.Gradient = aGrad;
0153 return aResult;
0154 }
0155
0156
0157 for (int i = 1; i <= aN; ++i)
0158 {
0159 for (int j = 1; j <= aN; ++j)
0160 {
0161 aH(i, j) = (i == j) ? 1.0 : 0.0;
0162 }
0163 }
0164 }
0165
0166
0167 for (int i = aLower; i <= aUpper; ++i)
0168 {
0169 aXNew(i) = aX(i) + aLineResult.Alpha * aDir(i);
0170 }
0171
0172
0173 for (int i = 1; i <= aN; ++i)
0174 {
0175 aS(i) = aXNew(aLower + i - 1) - aX(aLower + i - 1);
0176 }
0177
0178
0179 if (!theFunc.Gradient(aXNew, aGradNew))
0180 {
0181 aResult.Status = Status::NumericalError;
0182 aResult.Solution = aX;
0183 aResult.Value = aFx;
0184 return aResult;
0185 }
0186
0187
0188 aGradNorm = 0.0;
0189 for (int i = aLower; i <= aUpper; ++i)
0190 {
0191 aGradNorm += MathUtils::Sqr(aGradNew(i));
0192 }
0193 aGradNorm = std::sqrt(aGradNorm);
0194
0195 if (aGradNorm < theConfig.FTolerance)
0196 {
0197 aResult.Status = Status::OK;
0198 aResult.Solution = aXNew;
0199 aResult.Value = aLineResult.FNew;
0200 aResult.Gradient = aGradNew;
0201 return aResult;
0202 }
0203
0204
0205 double aMaxDiff = 0.0;
0206 for (int i = aLower; i <= aUpper; ++i)
0207 {
0208 aMaxDiff = std::max(aMaxDiff, std::abs(aXNew(i) - aX(i)));
0209 }
0210 if (aMaxDiff < theConfig.XTolerance)
0211 {
0212 aResult.Status = Status::OK;
0213 aResult.Solution = aXNew;
0214 aResult.Value = aLineResult.FNew;
0215 aResult.Gradient = aGradNew;
0216 return aResult;
0217 }
0218
0219
0220 for (int i = 1; i <= aN; ++i)
0221 {
0222 aY(i) = aGradNew(aLower + i - 1) - aGrad(aLower + i - 1);
0223 }
0224
0225
0226 double aSY = 0.0;
0227 for (int i = 1; i <= aN; ++i)
0228 {
0229 aSY += aS(i) * aY(i);
0230 }
0231
0232
0233 if (aSY > MathUtils::THE_ZERO_TOL)
0234 {
0235
0236
0237 const double aRho = 1.0 / aSY;
0238
0239
0240 math_Vector aHy(1, aN, 0.0);
0241 for (int i = 1; i <= aN; ++i)
0242 {
0243 for (int j = 1; j <= aN; ++j)
0244 {
0245 aHy(i) += aH(i, j) * aY(j);
0246 }
0247 }
0248
0249
0250 double aYHy = 0.0;
0251 for (int i = 1; i <= aN; ++i)
0252 {
0253 aYHy += aY(i) * aHy(i);
0254 }
0255
0256
0257
0258 const double aFactor = 1.0 + aRho * aYHy;
0259
0260 for (int i = 1; i <= aN; ++i)
0261 {
0262 for (int j = 1; j <= aN; ++j)
0263 {
0264 aH(i, j) =
0265 aH(i, j) - aRho * (aHy(i) * aS(j) + aS(i) * aHy(j)) + aFactor * aRho * aS(i) * aS(j);
0266 }
0267 }
0268 }
0269
0270
0271 aX = aXNew;
0272 aGrad = aGradNew;
0273 aFx = aLineResult.FNew;
0274 }
0275
0276
0277 aResult.Status = Status::MaxIterations;
0278 aResult.Solution = aX;
0279 aResult.Value = aFx;
0280 aResult.Gradient = aGrad;
0281 return aResult;
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294 template <typename Function>
0295 VectorResult BFGSNumerical(Function& theFunc,
0296 const math_Vector& theStartingPoint,
0297 double theGradStep = 1.0e-8,
0298 const Config& theConfig = Config())
0299 {
0300
0301 class FuncWithGradient
0302 {
0303 public:
0304 FuncWithGradient(Function& theF, double theStep)
0305 : myFunc(theF),
0306 myStep(theStep)
0307 {
0308 }
0309
0310 bool Value(const math_Vector& theX, double& theF) { return myFunc.Value(theX, theF); }
0311
0312 bool Gradient(const math_Vector& theX, math_Vector& theGrad)
0313 {
0314 math_Vector aXMod = theX;
0315 return MathUtils::NumericalGradientAdaptive(myFunc, aXMod, theGrad, myStep);
0316 }
0317
0318 private:
0319 Function& myFunc;
0320 double myStep;
0321 };
0322
0323 FuncWithGradient aWrapper(theFunc, theGradStep);
0324 return BFGS(aWrapper, theStartingPoint, theConfig);
0325 }
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 template <typename Function>
0338 VectorResult LBFGS(Function& theFunc,
0339 const math_Vector& theStartingPoint,
0340 int theMemorySize = 10,
0341 const Config& theConfig = Config())
0342 {
0343 VectorResult aResult;
0344
0345 const int aLower = theStartingPoint.Lower();
0346 const int aUpper = theStartingPoint.Upper();
0347 const int aN = aUpper - aLower + 1;
0348 const int aM = theMemorySize;
0349
0350 math_Vector aX(aLower, aUpper);
0351 aX = theStartingPoint;
0352
0353 double aFx = 0.0;
0354 if (!theFunc.Value(aX, aFx))
0355 {
0356 aResult.Status = Status::NumericalError;
0357 return aResult;
0358 }
0359
0360 math_Vector aGrad(aLower, aUpper);
0361 if (!theFunc.Gradient(aX, aGrad))
0362 {
0363 aResult.Status = Status::NumericalError;
0364 return aResult;
0365 }
0366
0367
0368 NCollection_DynamicArray<math_Vector> aSVec;
0369 NCollection_DynamicArray<math_Vector> aYVec;
0370 math_Vector aRhoVec(0, aM - 1, 0.0);
0371 for (int i = 0; i < aM; ++i)
0372 {
0373 aSVec.Append(math_Vector(1, aN));
0374 aYVec.Append(math_Vector(1, aN));
0375 }
0376 int aHead = 0;
0377 int aCount = 0;
0378
0379 math_Vector aDir(aLower, aUpper);
0380 math_Vector aXNew(aLower, aUpper);
0381 math_Vector aGradNew(aLower, aUpper);
0382 math_Vector aQ(1, aN);
0383 math_Vector aAlphaVec(0, aM - 1);
0384
0385 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0386 {
0387 aResult.NbIterations = anIter + 1;
0388
0389
0390 double aGradNorm = 0.0;
0391 for (int i = aLower; i <= aUpper; ++i)
0392 {
0393 aGradNorm += MathUtils::Sqr(aGrad(i));
0394 }
0395 if (std::sqrt(aGradNorm) < theConfig.FTolerance)
0396 {
0397 aResult.Status = Status::OK;
0398 aResult.Solution = aX;
0399 aResult.Value = aFx;
0400 aResult.Gradient = aGrad;
0401 return aResult;
0402 }
0403
0404
0405
0406 for (int i = 1; i <= aN; ++i)
0407 {
0408 aQ(i) = aGrad(aLower + i - 1);
0409 }
0410
0411
0412 for (int k = aCount - 1; k >= 0; --k)
0413 {
0414 const int aIdx = (aHead + k) % aM;
0415 aAlphaVec(aIdx) = aRhoVec(aIdx) * MathUtils::DotProduct(aSVec.Value(aIdx), aQ);
0416 for (int i = 1; i <= aN; ++i)
0417 {
0418 aQ(i) -= aAlphaVec(aIdx) * aYVec.Value(aIdx)(i);
0419 }
0420 }
0421
0422
0423 double aGamma = 1.0;
0424 if (aCount > 0)
0425 {
0426 const int aLastIdx = (aHead + aCount - 1) % aM;
0427 double aYY = MathUtils::DotProduct(aYVec.Value(aLastIdx), aYVec.Value(aLastIdx));
0428 if (aYY > MathUtils::THE_ZERO_TOL)
0429 {
0430 aGamma = 1.0 / (aRhoVec(aLastIdx) * aYY);
0431 }
0432 }
0433
0434
0435 math_Vector aR(1, aN);
0436 for (int i = 1; i <= aN; ++i)
0437 {
0438 aR(i) = aGamma * aQ(i);
0439 }
0440
0441
0442 for (int k = 0; k < aCount; ++k)
0443 {
0444 const int aIdx = (aHead + k) % aM;
0445 const double aBeta = aRhoVec(aIdx) * MathUtils::DotProduct(aYVec.Value(aIdx), aR);
0446 for (int i = 1; i <= aN; ++i)
0447 {
0448 aR(i) += (aAlphaVec(aIdx) - aBeta) * aSVec.Value(aIdx)(i);
0449 }
0450 }
0451
0452
0453 for (int i = aLower; i <= aUpper; ++i)
0454 {
0455 aDir(i) = -aR(i - aLower + 1);
0456 }
0457
0458
0459 MathUtils::LineSearchResult aLineResult =
0460 MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, 1.0, 1.0e-4, 0.5, 50);
0461
0462 if (!aLineResult.IsValid)
0463 {
0464
0465 for (int i = aLower; i <= aUpper; ++i)
0466 {
0467 aDir(i) = -aGrad(i);
0468 }
0469 aLineResult = MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, 1.0, 1.0e-4, 0.5, 50);
0470
0471 if (!aLineResult.IsValid)
0472 {
0473 aResult.Status = Status::NotConverged;
0474 aResult.Solution = aX;
0475 aResult.Value = aFx;
0476 return aResult;
0477 }
0478
0479 aCount = 0;
0480 }
0481
0482
0483 for (int i = aLower; i <= aUpper; ++i)
0484 {
0485 aXNew(i) = aX(i) + aLineResult.Alpha * aDir(i);
0486 }
0487
0488
0489 double aMaxDiff = 0.0;
0490 for (int i = aLower; i <= aUpper; ++i)
0491 {
0492 aMaxDiff = std::max(aMaxDiff, std::abs(aXNew(i) - aX(i)));
0493 }
0494 if (aMaxDiff < theConfig.XTolerance)
0495 {
0496 if (!theFunc.Gradient(aXNew, aGradNew))
0497 {
0498 aGradNew = aGrad;
0499 }
0500 aResult.Status = Status::OK;
0501 aResult.Solution = aXNew;
0502 aResult.Value = aLineResult.FNew;
0503 aResult.Gradient = aGradNew;
0504 return aResult;
0505 }
0506
0507
0508 if (!theFunc.Gradient(aXNew, aGradNew))
0509 {
0510 aResult.Status = Status::NumericalError;
0511 aResult.Solution = aX;
0512 aResult.Value = aFx;
0513 return aResult;
0514 }
0515
0516
0517 const int aNewIdx = (aHead + aCount) % aM;
0518 for (int i = 1; i <= aN; ++i)
0519 {
0520 aSVec.ChangeValue(aNewIdx)(i) = aXNew(aLower + i - 1) - aX(aLower + i - 1);
0521 aYVec.ChangeValue(aNewIdx)(i) = aGradNew(aLower + i - 1) - aGrad(aLower + i - 1);
0522 }
0523
0524 double aSY = MathUtils::DotProduct(aSVec.Value(aNewIdx), aYVec.Value(aNewIdx));
0525 if (aSY > MathUtils::THE_ZERO_TOL)
0526 {
0527 aRhoVec(aNewIdx) = 1.0 / aSY;
0528 if (aCount < aM)
0529 {
0530 ++aCount;
0531 }
0532 else
0533 {
0534 aHead = (aHead + 1) % aM;
0535 }
0536 }
0537
0538
0539 aX = aXNew;
0540 aGrad = aGradNew;
0541 aFx = aLineResult.FNew;
0542 }
0543
0544 aResult.Status = Status::MaxIterations;
0545 aResult.Solution = aX;
0546 aResult.Value = aFx;
0547 aResult.Gradient = aGrad;
0548 return aResult;
0549 }
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565 template <typename Function>
0566 VectorResult BFGSBounded(Function& theFunc,
0567 const math_Vector& theStartingPoint,
0568 const math_Vector& theLowerBounds,
0569 const math_Vector& theUpperBounds,
0570 const Config& theConfig = Config())
0571 {
0572 VectorResult aResult;
0573
0574 const int aLower = theStartingPoint.Lower();
0575 const int aUpper = theStartingPoint.Upper();
0576 const int aN = aUpper - aLower + 1;
0577
0578
0579 if (theLowerBounds.Length() != aN || theUpperBounds.Length() != aN)
0580 {
0581 aResult.Status = Status::InvalidInput;
0582 return aResult;
0583 }
0584
0585
0586 auto ClampToBounds = [&](math_Vector& theX) {
0587 for (int i = aLower; i <= aUpper; ++i)
0588 {
0589 const int aBndIdx = theLowerBounds.Lower() + (i - aLower);
0590 if (theX(i) < theLowerBounds(aBndIdx))
0591 {
0592 theX(i) = theLowerBounds(aBndIdx);
0593 }
0594 if (theX(i) > theUpperBounds(aBndIdx))
0595 {
0596 theX(i) = theUpperBounds(aBndIdx);
0597 }
0598 }
0599 };
0600
0601
0602 auto ProjectGradient = [&](const math_Vector& theX, math_Vector& theGrad) {
0603 for (int i = aLower; i <= aUpper; ++i)
0604 {
0605 const int aBndIdx = theLowerBounds.Lower() + (i - aLower);
0606 const double aTol = MathUtils::THE_EPSILON * std::max(1.0, std::abs(theX(i)));
0607
0608
0609 if (theX(i) - theLowerBounds(aBndIdx) < aTol && theGrad(i) > 0.0)
0610 {
0611 theGrad(i) = 0.0;
0612 }
0613
0614 if (theUpperBounds(aBndIdx) - theX(i) < aTol && theGrad(i) < 0.0)
0615 {
0616 theGrad(i) = 0.0;
0617 }
0618 }
0619 };
0620
0621
0622 math_Vector aX(aLower, aUpper);
0623 aX = theStartingPoint;
0624 ClampToBounds(aX);
0625
0626 double aFx = 0.0;
0627 if (!theFunc.Value(aX, aFx))
0628 {
0629 aResult.Status = Status::NumericalError;
0630 return aResult;
0631 }
0632
0633
0634 math_Vector aGrad(aLower, aUpper);
0635 if (!theFunc.Gradient(aX, aGrad))
0636 {
0637 aResult.Status = Status::NumericalError;
0638 return aResult;
0639 }
0640 ProjectGradient(aX, aGrad);
0641
0642
0643 double aGradNorm = 0.0;
0644 for (int i = aLower; i <= aUpper; ++i)
0645 {
0646 aGradNorm += MathUtils::Sqr(aGrad(i));
0647 }
0648 aGradNorm = std::sqrt(aGradNorm);
0649
0650 if (aGradNorm < theConfig.FTolerance)
0651 {
0652 aResult.Status = Status::OK;
0653 aResult.Solution = aX;
0654 aResult.Value = aFx;
0655 aResult.Gradient = aGrad;
0656 return aResult;
0657 }
0658
0659
0660 math_Matrix aH(1, aN, 1, aN, 0.0);
0661 for (int i = 1; i <= aN; ++i)
0662 {
0663 aH(i, i) = 1.0;
0664 }
0665
0666
0667 math_Vector aDir(aLower, aUpper);
0668 math_Vector aXNew(aLower, aUpper);
0669 math_Vector aGradNew(aLower, aUpper);
0670 math_Vector aS(1, aN);
0671 math_Vector aY(1, aN);
0672
0673 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0674 {
0675 aResult.NbIterations = anIter + 1;
0676
0677
0678 for (int i = 1; i <= aN; ++i)
0679 {
0680 double aSum = 0.0;
0681 for (int j = 1; j <= aN; ++j)
0682 {
0683 aSum += aH(i, j) * aGrad(aLower + j - 1);
0684 }
0685 aDir(aLower + i - 1) = -aSum;
0686 }
0687
0688
0689 double aAlphaMax = 1.0;
0690 for (int i = aLower; i <= aUpper; ++i)
0691 {
0692 const int aBndIdx = theLowerBounds.Lower() + (i - aLower);
0693 if (aDir(i) < -MathUtils::THE_EPSILON)
0694 {
0695
0696 double aMaxStep = (theLowerBounds(aBndIdx) - aX(i)) / aDir(i);
0697 aAlphaMax = std::min(aAlphaMax, aMaxStep);
0698 }
0699 else if (aDir(i) > MathUtils::THE_EPSILON)
0700 {
0701
0702 double aMaxStep = (theUpperBounds(aBndIdx) - aX(i)) / aDir(i);
0703 aAlphaMax = std::min(aAlphaMax, aMaxStep);
0704 }
0705 }
0706 aAlphaMax = std::max(aAlphaMax, MathUtils::THE_EPSILON);
0707
0708 MathUtils::LineSearchResult aLineResult =
0709 MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, aAlphaMax, 1.0e-4, 0.5, 50);
0710
0711 if (!aLineResult.IsValid || aLineResult.Alpha < MathUtils::THE_EPSILON)
0712 {
0713
0714 for (int i = aLower; i <= aUpper; ++i)
0715 {
0716 aDir(i) = -aGrad(i);
0717 }
0718
0719 aAlphaMax = 1.0;
0720 for (int i = aLower; i <= aUpper; ++i)
0721 {
0722 const int aBndIdx = theLowerBounds.Lower() + (i - aLower);
0723 if (aDir(i) < -MathUtils::THE_EPSILON)
0724 {
0725 aAlphaMax = std::min(aAlphaMax, (theLowerBounds(aBndIdx) - aX(i)) / aDir(i));
0726 }
0727 else if (aDir(i) > MathUtils::THE_EPSILON)
0728 {
0729 aAlphaMax = std::min(aAlphaMax, (theUpperBounds(aBndIdx) - aX(i)) / aDir(i));
0730 }
0731 }
0732 aAlphaMax = std::max(aAlphaMax, MathUtils::THE_EPSILON);
0733
0734 aLineResult =
0735 MathUtils::ArmijoBacktrack(theFunc, aX, aDir, aGrad, aFx, aAlphaMax, 1.0e-4, 0.5, 50);
0736
0737 if (!aLineResult.IsValid)
0738 {
0739 aResult.Status = Status::NotConverged;
0740 aResult.Solution = aX;
0741 aResult.Value = aFx;
0742 aResult.Gradient = aGrad;
0743 return aResult;
0744 }
0745
0746
0747 for (int i = 1; i <= aN; ++i)
0748 {
0749 for (int j = 1; j <= aN; ++j)
0750 {
0751 aH(i, j) = (i == j) ? 1.0 : 0.0;
0752 }
0753 }
0754 }
0755
0756
0757 for (int i = aLower; i <= aUpper; ++i)
0758 {
0759 aXNew(i) = aX(i) + aLineResult.Alpha * aDir(i);
0760 }
0761 ClampToBounds(aXNew);
0762
0763
0764 for (int i = 1; i <= aN; ++i)
0765 {
0766 aS(i) = aXNew(aLower + i - 1) - aX(aLower + i - 1);
0767 }
0768
0769
0770 double aFxNew = 0.0;
0771 if (!theFunc.Value(aXNew, aFxNew))
0772 {
0773 aResult.Status = Status::NumericalError;
0774 aResult.Solution = aX;
0775 aResult.Value = aFx;
0776 return aResult;
0777 }
0778
0779 if (!theFunc.Gradient(aXNew, aGradNew))
0780 {
0781 aResult.Status = Status::NumericalError;
0782 aResult.Solution = aX;
0783 aResult.Value = aFx;
0784 return aResult;
0785 }
0786 ProjectGradient(aXNew, aGradNew);
0787
0788
0789 aGradNorm = 0.0;
0790 for (int i = aLower; i <= aUpper; ++i)
0791 {
0792 aGradNorm += MathUtils::Sqr(aGradNew(i));
0793 }
0794 aGradNorm = std::sqrt(aGradNorm);
0795
0796 if (aGradNorm < theConfig.FTolerance)
0797 {
0798 aResult.Status = Status::OK;
0799 aResult.Solution = aXNew;
0800 aResult.Value = aFxNew;
0801 aResult.Gradient = aGradNew;
0802 return aResult;
0803 }
0804
0805
0806 double aMaxDiff = 0.0;
0807 for (int i = aLower; i <= aUpper; ++i)
0808 {
0809 aMaxDiff = std::max(aMaxDiff, std::abs(aXNew(i) - aX(i)));
0810 }
0811 if (aMaxDiff < theConfig.XTolerance)
0812 {
0813 aResult.Status = Status::OK;
0814 aResult.Solution = aXNew;
0815 aResult.Value = aFxNew;
0816 aResult.Gradient = aGradNew;
0817 return aResult;
0818 }
0819
0820
0821 for (int i = 1; i <= aN; ++i)
0822 {
0823 aY(i) = aGradNew(aLower + i - 1) - aGrad(aLower + i - 1);
0824 }
0825
0826
0827 double aSY = 0.0;
0828 for (int i = 1; i <= aN; ++i)
0829 {
0830 aSY += aS(i) * aY(i);
0831 }
0832
0833 if (aSY > MathUtils::THE_ZERO_TOL)
0834 {
0835 const double aRho = 1.0 / aSY;
0836
0837 math_Vector aHy(1, aN, 0.0);
0838 for (int i = 1; i <= aN; ++i)
0839 {
0840 for (int j = 1; j <= aN; ++j)
0841 {
0842 aHy(i) += aH(i, j) * aY(j);
0843 }
0844 }
0845
0846 double aYHy = 0.0;
0847 for (int i = 1; i <= aN; ++i)
0848 {
0849 aYHy += aY(i) * aHy(i);
0850 }
0851
0852 const double aFactor = 1.0 + aRho * aYHy;
0853 for (int i = 1; i <= aN; ++i)
0854 {
0855 for (int j = 1; j <= aN; ++j)
0856 {
0857 aH(i, j) =
0858 aH(i, j) - aRho * (aHy(i) * aS(j) + aS(i) * aHy(j)) + aFactor * aRho * aS(i) * aS(j);
0859 }
0860 }
0861 }
0862
0863 aX = aXNew;
0864 aGrad = aGradNew;
0865 aFx = aFxNew;
0866 }
0867
0868 aResult.Status = Status::MaxIterations;
0869 aResult.Solution = aX;
0870 aResult.Value = aFx;
0871 aResult.Gradient = aGrad;
0872 return aResult;
0873 }
0874
0875 }
0876
0877 #endif